00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef _BOOST_UBLAS_MATRIX_SPARSE_
00014 #define _BOOST_UBLAS_MATRIX_SPARSE_
00015
00016 #include <boost/numeric/ublas/vector_sparse.hpp>
00017 #include <boost/numeric/ublas/matrix_expression.hpp>
00018 #include <boost/numeric/ublas/detail/matrix_assign.hpp>
00019 #if BOOST_UBLAS_TYPE_CHECK
00020 #include <boost/numeric/ublas/matrix.hpp>
00021 #endif
00022
00023
00024
00025 namespace boost { namespace numeric { namespace ublas {
00026
00027 #ifdef BOOST_UBLAS_STRICT_MATRIX_SPARSE
00028
00029 template<class M>
00030 class sparse_matrix_element:
00031 public container_reference<M> {
00032 public:
00033 typedef M matrix_type;
00034 typedef typename M::size_type size_type;
00035 typedef typename M::value_type value_type;
00036 typedef const value_type &const_reference;
00037 typedef value_type *pointer;
00038 typedef const value_type *const_pointer;
00039
00040 private:
00041
00042 void get_d () const {
00043 const_pointer p = (*this) ().find_element (i_, j_);
00044 if (p)
00045 d_ = *p;
00046 else
00047 d_ = value_type();
00048 }
00049
00050 void set (const value_type &s) const {
00051 pointer p = (*this) ().find_element (i_, j_);
00052 if (!p)
00053 (*this) ().insert_element (i_, j_, s);
00054 else
00055 *p = s;
00056 }
00057
00058 public:
00059
00060 BOOST_UBLAS_INLINE
00061 sparse_matrix_element (matrix_type &m, size_type i, size_type j):
00062 container_reference<matrix_type> (m), i_ (i), j_ (j) {
00063 }
00064 BOOST_UBLAS_INLINE
00065 sparse_matrix_element (const sparse_matrix_element &p):
00066 container_reference<matrix_type> (p), i_ (p.i_), j_ (p.j_) {}
00067 BOOST_UBLAS_INLINE
00068 ~sparse_matrix_element () {
00069 }
00070
00071
00072 BOOST_UBLAS_INLINE
00073 sparse_matrix_element &operator = (const sparse_matrix_element &p) {
00074
00075 p.get_d ();
00076 set (p.d_);
00077 return *this;
00078 }
00079 template<class D>
00080 BOOST_UBLAS_INLINE
00081 sparse_matrix_element &operator = (const D &d) {
00082 set (d);
00083 return *this;
00084 }
00085 template<class D>
00086 BOOST_UBLAS_INLINE
00087 sparse_matrix_element &operator += (const D &d) {
00088 get_d ();
00089 d_ += d;
00090 set (d_);
00091 return *this;
00092 }
00093 template<class D>
00094 BOOST_UBLAS_INLINE
00095 sparse_matrix_element &operator -= (const D &d) {
00096 get_d ();
00097 d_ -= d;
00098 set (d_);
00099 return *this;
00100 }
00101 template<class D>
00102 BOOST_UBLAS_INLINE
00103 sparse_matrix_element &operator *= (const D &d) {
00104 get_d ();
00105 d_ *= d;
00106 set (d_);
00107 return *this;
00108 }
00109 template<class D>
00110 BOOST_UBLAS_INLINE
00111 sparse_matrix_element &operator /= (const D &d) {
00112 get_d ();
00113 d_ /= d;
00114 set (d_);
00115 return *this;
00116 }
00117
00118
00119 template<class D>
00120 BOOST_UBLAS_INLINE
00121 bool operator == (const D &d) const {
00122 get_d ();
00123 return d_ == d;
00124 }
00125 template<class D>
00126 BOOST_UBLAS_INLINE
00127 bool operator != (const D &d) const {
00128 get_d ();
00129 return d_ != d;
00130 }
00131
00132
00133 BOOST_UBLAS_INLINE
00134 operator const_reference () const {
00135 get_d ();
00136 return d_;
00137 }
00138
00139
00140 BOOST_UBLAS_INLINE
00141 value_type& ref () const {
00142 const pointer p = (*this) ().find_element (i_, j_);
00143 if (!p)
00144 return (*this) ().insert_element (i_, j_, value_type());
00145 else
00146 return *p;
00147 }
00148
00149 private:
00150 size_type i_;
00151 size_type j_;
00152 mutable value_type d_;
00153 };
00154
00155
00156
00157
00158 namespace detail {
00159 template <class V>
00160 struct element_reference<sparse_matrix_element<V> > {
00161 typedef typename V::value_type& reference;
00162 static reference get_reference (const sparse_matrix_element<V>& sve)
00163 {
00164 return sve.ref ();
00165 }
00166 };
00167 }
00168
00169
00170 template<class M>
00171 struct type_traits<sparse_matrix_element<M> > {
00172 typedef typename M::value_type element_type;
00173 typedef type_traits<sparse_matrix_element<M> > self_type;
00174 typedef typename type_traits<element_type>::value_type value_type;
00175 typedef typename type_traits<element_type>::const_reference const_reference;
00176 typedef sparse_matrix_element<M> reference;
00177 typedef typename type_traits<element_type>::real_type real_type;
00178 typedef typename type_traits<element_type>::precision_type precision_type;
00179
00180 static const unsigned plus_complexity = type_traits<element_type>::plus_complexity;
00181 static const unsigned multiplies_complexity = type_traits<element_type>::multiplies_complexity;
00182
00183 static
00184 BOOST_UBLAS_INLINE
00185 real_type real (const_reference t) {
00186 return type_traits<element_type>::real (t);
00187 }
00188 static
00189 BOOST_UBLAS_INLINE
00190 real_type imag (const_reference t) {
00191 return type_traits<element_type>::imag (t);
00192 }
00193 static
00194 BOOST_UBLAS_INLINE
00195 value_type conj (const_reference t) {
00196 return type_traits<element_type>::conj (t);
00197 }
00198
00199 static
00200 BOOST_UBLAS_INLINE
00201 real_type type_abs (const_reference t) {
00202 return type_traits<element_type>::type_abs (t);
00203 }
00204 static
00205 BOOST_UBLAS_INLINE
00206 value_type type_sqrt (const_reference t) {
00207 return type_traits<element_type>::type_sqrt (t);
00208 }
00209
00210 static
00211 BOOST_UBLAS_INLINE
00212 real_type norm_1 (const_reference t) {
00213 return type_traits<element_type>::norm_1 (t);
00214 }
00215 static
00216 BOOST_UBLAS_INLINE
00217 real_type norm_2 (const_reference t) {
00218 return type_traits<element_type>::norm_2 (t);
00219 }
00220 static
00221 BOOST_UBLAS_INLINE
00222 real_type norm_inf (const_reference t) {
00223 return type_traits<element_type>::norm_inf (t);
00224 }
00225
00226 static
00227 BOOST_UBLAS_INLINE
00228 bool equals (const_reference t1, const_reference t2) {
00229 return type_traits<element_type>::equals (t1, t2);
00230 }
00231 };
00232
00233 template<class M1, class T2>
00234 struct promote_traits<sparse_matrix_element<M1>, T2> {
00235 typedef typename promote_traits<typename sparse_matrix_element<M1>::value_type, T2>::promote_type promote_type;
00236 };
00237 template<class T1, class M2>
00238 struct promote_traits<T1, sparse_matrix_element<M2> > {
00239 typedef typename promote_traits<T1, typename sparse_matrix_element<M2>::value_type>::promote_type promote_type;
00240 };
00241 template<class M1, class M2>
00242 struct promote_traits<sparse_matrix_element<M1>, sparse_matrix_element<M2> > {
00243 typedef typename promote_traits<typename sparse_matrix_element<M1>::value_type,
00244 typename sparse_matrix_element<M2>::value_type>::promote_type promote_type;
00245 };
00246
00247 #endif
00248
00267 template<class T, class L, class A>
00268 class mapped_matrix:
00269 public matrix_container<mapped_matrix<T, L, A> > {
00270
00271 typedef T &true_reference;
00272 typedef T *pointer;
00273 typedef const T * const_pointer;
00274 typedef L layout_type;
00275 typedef mapped_matrix<T, L, A> self_type;
00276 public:
00277 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
00278 using matrix_container<self_type>::operator ();
00279 #endif
00280 typedef typename A::size_type size_type;
00281 typedef typename A::difference_type difference_type;
00282 typedef T value_type;
00283 typedef A array_type;
00284 typedef const T &const_reference;
00285 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
00286 typedef typename detail::map_traits<A, T>::reference reference;
00287 #else
00288 typedef sparse_matrix_element<self_type> reference;
00289 #endif
00290 typedef const matrix_reference<const self_type> const_closure_type;
00291 typedef matrix_reference<self_type> closure_type;
00292 typedef mapped_vector<T, A> vector_temporary_type;
00293 typedef self_type matrix_temporary_type;
00294 typedef sparse_tag storage_category;
00295 typedef typename L::orientation_category orientation_category;
00296
00297
00298 BOOST_UBLAS_INLINE
00299 mapped_matrix ():
00300 matrix_container<self_type> (),
00301 size1_ (0), size2_ (0), data_ () {}
00302 BOOST_UBLAS_INLINE
00303 mapped_matrix (size_type size1, size_type size2, size_type non_zeros = 0):
00304 matrix_container<self_type> (),
00305 size1_ (size1), size2_ (size2), data_ () {
00306 detail::map_reserve (data (), restrict_capacity (non_zeros));
00307 }
00308 BOOST_UBLAS_INLINE
00309 mapped_matrix (const mapped_matrix &m):
00310 matrix_container<self_type> (),
00311 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
00312 template<class AE>
00313 BOOST_UBLAS_INLINE
00314 mapped_matrix (const matrix_expression<AE> &ae, size_type non_zeros = 0):
00315 matrix_container<self_type> (),
00316 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () {
00317 detail::map_reserve (data (), restrict_capacity (non_zeros));
00318 matrix_assign<scalar_assign> (*this, ae);
00319 }
00320
00321
00322 BOOST_UBLAS_INLINE
00323 size_type size1 () const {
00324 return size1_;
00325 }
00326 BOOST_UBLAS_INLINE
00327 size_type size2 () const {
00328 return size2_;
00329 }
00330 BOOST_UBLAS_INLINE
00331 size_type nnz_capacity () const {
00332 return detail::map_capacity (data ());
00333 }
00334 BOOST_UBLAS_INLINE
00335 size_type nnz () const {
00336 return data (). size ();
00337 }
00338
00339
00340 BOOST_UBLAS_INLINE
00341 const array_type &data () const {
00342 return data_;
00343 }
00344 BOOST_UBLAS_INLINE
00345 array_type &data () {
00346 return data_;
00347 }
00348
00349
00350 private:
00351 BOOST_UBLAS_INLINE
00352 size_type restrict_capacity (size_type non_zeros) const {
00353
00354
00355 if (size1_ > 0 && non_zeros / size1_ >= size2_)
00356 non_zeros = size1_ * size2_;
00357 return non_zeros;
00358 }
00359 public:
00360 BOOST_UBLAS_INLINE
00361 void resize (size_type size1, size_type size2, bool preserve = true) {
00362
00363 BOOST_UBLAS_CHECK (!preserve, internal_logic ());
00364 size1_ = size1;
00365 size2_ = size2;
00366 data ().clear ();
00367 }
00368
00369
00370 BOOST_UBLAS_INLINE
00371 void reserve (size_type non_zeros, bool preserve = true) {
00372 detail::map_reserve (data (), restrict_capacity (non_zeros));
00373 }
00374
00375
00376 BOOST_UBLAS_INLINE
00377 pointer find_element (size_type i, size_type j) {
00378 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
00379 }
00380 BOOST_UBLAS_INLINE
00381 const_pointer find_element (size_type i, size_type j) const {
00382 const size_type element = layout_type::element (i, size1_, j, size2_);
00383 const_subiterator_type it (data ().find (element));
00384 if (it == data ().end ())
00385 return 0;
00386 BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ());
00387 return &(*it).second;
00388 }
00389
00390
00391 BOOST_UBLAS_INLINE
00392 const_reference operator () (size_type i, size_type j) const {
00393 const size_type element = layout_type::element (i, size1_, j, size2_);
00394 const_subiterator_type it (data ().find (element));
00395 if (it == data ().end ())
00396 return zero_;
00397 BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ());
00398 return (*it).second;
00399 }
00400 BOOST_UBLAS_INLINE
00401 reference operator () (size_type i, size_type j) {
00402 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
00403 const size_type element = layout_type::element (i, size1_, j, size2_);
00404 std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (element, value_type())));
00405 BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ());
00406 return (ii.first)->second;
00407 #else
00408 return reference (*this, i, j);
00409 #endif
00410 }
00411
00412
00413 BOOST_UBLAS_INLINE
00414 true_reference insert_element (size_type i, size_type j, const_reference t) {
00415 BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ());
00416 const size_type element = layout_type::element (i, size1_, j, size2_);
00417 std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (element, t)));
00418 BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ());
00419 if (!ii.second)
00420 (ii.first)->second = t;
00421 return (ii.first)->second;
00422 }
00423 BOOST_UBLAS_INLINE
00424 void erase_element (size_type i, size_type j) {
00425 subiterator_type it = data ().find (layout_type::element (i, size1_, j, size2_));
00426 if (it == data ().end ())
00427 return;
00428 data ().erase (it);
00429 }
00430
00431
00432 BOOST_UBLAS_INLINE
00433 void clear () {
00434 data ().clear ();
00435 }
00436
00437
00438 BOOST_UBLAS_INLINE
00439 mapped_matrix &operator = (const mapped_matrix &m) {
00440 if (this != &m) {
00441 size1_ = m.size1_;
00442 size2_ = m.size2_;
00443 data () = m.data ();
00444 }
00445 return *this;
00446 }
00447 template<class C>
00448 BOOST_UBLAS_INLINE
00449 mapped_matrix &operator = (const matrix_container<C> &m) {
00450 resize (m ().size1 (), m ().size2 (), false);
00451 assign (m);
00452 return *this;
00453 }
00454 BOOST_UBLAS_INLINE
00455 mapped_matrix &assign_temporary (mapped_matrix &m) {
00456 swap (m);
00457 return *this;
00458 }
00459 template<class AE>
00460 BOOST_UBLAS_INLINE
00461 mapped_matrix &operator = (const matrix_expression<AE> &ae) {
00462 self_type temporary (ae, detail::map_capacity (data ()));
00463 return assign_temporary (temporary);
00464 }
00465 template<class AE>
00466 BOOST_UBLAS_INLINE
00467 mapped_matrix &assign (const matrix_expression<AE> &ae) {
00468 matrix_assign<scalar_assign> (*this, ae);
00469 return *this;
00470 }
00471 template<class AE>
00472 BOOST_UBLAS_INLINE
00473 mapped_matrix& operator += (const matrix_expression<AE> &ae) {
00474 self_type temporary (*this + ae, detail::map_capacity (data ()));
00475 return assign_temporary (temporary);
00476 }
00477 template<class C>
00478 BOOST_UBLAS_INLINE
00479 mapped_matrix &operator += (const matrix_container<C> &m) {
00480 plus_assign (m);
00481 return *this;
00482 }
00483 template<class AE>
00484 BOOST_UBLAS_INLINE
00485 mapped_matrix &plus_assign (const matrix_expression<AE> &ae) {
00486 matrix_assign<scalar_plus_assign> (*this, ae);
00487 return *this;
00488 }
00489 template<class AE>
00490 BOOST_UBLAS_INLINE
00491 mapped_matrix& operator -= (const matrix_expression<AE> &ae) {
00492 self_type temporary (*this - ae, detail::map_capacity (data ()));
00493 return assign_temporary (temporary);
00494 }
00495 template<class C>
00496 BOOST_UBLAS_INLINE
00497 mapped_matrix &operator -= (const matrix_container<C> &m) {
00498 minus_assign (m);
00499 return *this;
00500 }
00501 template<class AE>
00502 BOOST_UBLAS_INLINE
00503 mapped_matrix &minus_assign (const matrix_expression<AE> &ae) {
00504 matrix_assign<scalar_minus_assign> (*this, ae);
00505 return *this;
00506 }
00507 template<class AT>
00508 BOOST_UBLAS_INLINE
00509 mapped_matrix& operator *= (const AT &at) {
00510 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
00511 return *this;
00512 }
00513 template<class AT>
00514 BOOST_UBLAS_INLINE
00515 mapped_matrix& operator /= (const AT &at) {
00516 matrix_assign_scalar<scalar_divides_assign> (*this, at);
00517 return *this;
00518 }
00519
00520
00521 BOOST_UBLAS_INLINE
00522 void swap (mapped_matrix &m) {
00523 if (this != &m) {
00524 std::swap (size1_, m.size1_);
00525 std::swap (size2_, m.size2_);
00526 data ().swap (m.data ());
00527 }
00528 }
00529 BOOST_UBLAS_INLINE
00530 friend void swap (mapped_matrix &m1, mapped_matrix &m2) {
00531 m1.swap (m2);
00532 }
00533
00534
00535 private:
00536
00537 typedef typename A::const_iterator const_subiterator_type;
00538 typedef typename A::iterator subiterator_type;
00539
00540 BOOST_UBLAS_INLINE
00541 true_reference at_element (size_type i, size_type j) {
00542 const size_type element = layout_type::element (i, size1_, j, size2_);
00543 subiterator_type it (data ().find (element));
00544 BOOST_UBLAS_CHECK (it != data ().end(), bad_index ());
00545 BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ());
00546 return it->second;
00547 }
00548
00549 public:
00550 class const_iterator1;
00551 class iterator1;
00552 class const_iterator2;
00553 class iterator2;
00554 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
00555 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
00556 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
00557 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
00558
00559
00560
00561 const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
00562 const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
00563 const_subiterator_type it_end (data ().end ());
00564 size_type index1 = size_type (-1);
00565 size_type index2 = size_type (-1);
00566 while (rank == 1 && it != it_end) {
00567 index1 = layout_type::index_i ((*it).first, size1_, size2_);
00568 index2 = layout_type::index_j ((*it).first, size1_, size2_);
00569 if (direction > 0) {
00570 if ((index1 >= i && index2 == j) || (i >= size1_))
00571 break;
00572 ++ i;
00573 } else {
00574 if ((index1 <= i && index2 == j) || (i == 0))
00575 break;
00576 -- i;
00577 }
00578 it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
00579 }
00580 if (rank == 1 && index2 != j) {
00581 if (direction > 0)
00582 i = size1_;
00583 else
00584 i = 0;
00585 rank = 0;
00586 }
00587 return const_iterator1 (*this, rank, i, j, it);
00588 }
00589
00590 iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
00591 subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
00592 subiterator_type it_end (data ().end ());
00593 size_type index1 = size_type (-1);
00594 size_type index2 = size_type (-1);
00595 while (rank == 1 && it != it_end) {
00596 index1 = layout_type::index_i ((*it).first, size1_, size2_);
00597 index2 = layout_type::index_j ((*it).first, size1_, size2_);
00598 if (direction > 0) {
00599 if ((index1 >= i && index2 == j) || (i >= size1_))
00600 break;
00601 ++ i;
00602 } else {
00603 if ((index1 <= i && index2 == j) || (i == 0))
00604 break;
00605 -- i;
00606 }
00607 it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
00608 }
00609 if (rank == 1 && index2 != j) {
00610 if (direction > 0)
00611 i = size1_;
00612 else
00613 i = 0;
00614 rank = 0;
00615 }
00616 return iterator1 (*this, rank, i, j, it);
00617 }
00618
00619 const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
00620 const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
00621 const_subiterator_type it_end (data ().end ());
00622 size_type index1 = size_type (-1);
00623 size_type index2 = size_type (-1);
00624 while (rank == 1 && it != it_end) {
00625 index1 = layout_type::index_i ((*it).first, size1_, size2_);
00626 index2 = layout_type::index_j ((*it).first, size1_, size2_);
00627 if (direction > 0) {
00628 if ((index2 >= j && index1 == i) || (j >= size2_))
00629 break;
00630 ++ j;
00631 } else {
00632 if ((index2 <= j && index1 == i) || (j == 0))
00633 break;
00634 -- j;
00635 }
00636 it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
00637 }
00638 if (rank == 1 && index1 != i) {
00639 if (direction > 0)
00640 j = size2_;
00641 else
00642 j = 0;
00643 rank = 0;
00644 }
00645 return const_iterator2 (*this, rank, i, j, it);
00646 }
00647
00648 iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
00649 subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
00650 subiterator_type it_end (data ().end ());
00651 size_type index1 = size_type (-1);
00652 size_type index2 = size_type (-1);
00653 while (rank == 1 && it != it_end) {
00654 index1 = layout_type::index_i ((*it).first, size1_, size2_);
00655 index2 = layout_type::index_j ((*it).first, size1_, size2_);
00656 if (direction > 0) {
00657 if ((index2 >= j && index1 == i) || (j >= size2_))
00658 break;
00659 ++ j;
00660 } else {
00661 if ((index2 <= j && index1 == i) || (j == 0))
00662 break;
00663 -- j;
00664 }
00665 it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
00666 }
00667 if (rank == 1 && index1 != i) {
00668 if (direction > 0)
00669 j = size2_;
00670 else
00671 j = 0;
00672 rank = 0;
00673 }
00674 return iterator2 (*this, rank, i, j, it);
00675 }
00676
00677
00678 class const_iterator1:
00679 public container_const_reference<mapped_matrix>,
00680 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
00681 const_iterator1, value_type> {
00682 public:
00683 typedef typename mapped_matrix::value_type value_type;
00684 typedef typename mapped_matrix::difference_type difference_type;
00685 typedef typename mapped_matrix::const_reference reference;
00686 typedef const typename mapped_matrix::pointer pointer;
00687
00688 typedef const_iterator2 dual_iterator_type;
00689 typedef const_reverse_iterator2 dual_reverse_iterator_type;
00690
00691
00692 BOOST_UBLAS_INLINE
00693 const_iterator1 ():
00694 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
00695 BOOST_UBLAS_INLINE
00696 const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_subiterator_type &it):
00697 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
00698 BOOST_UBLAS_INLINE
00699 const_iterator1 (const iterator1 &it):
00700 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
00701
00702
00703 BOOST_UBLAS_INLINE
00704 const_iterator1 &operator ++ () {
00705 if (rank_ == 1 && layout_type::fast_i ())
00706 ++ it_;
00707 else
00708 *this = (*this) ().find1 (rank_, index1 () + 1, j_, 1);
00709 return *this;
00710 }
00711 BOOST_UBLAS_INLINE
00712 const_iterator1 &operator -- () {
00713 if (rank_ == 1 && layout_type::fast_i ())
00714 -- it_;
00715 else
00716 *this = (*this) ().find1 (rank_, index1 () - 1, j_, -1);
00717 return *this;
00718 }
00719
00720
00721 BOOST_UBLAS_INLINE
00722 const_reference operator * () const {
00723 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
00724 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
00725 if (rank_ == 1) {
00726 return (*it_).second;
00727 } else {
00728 return (*this) () (i_, j_);
00729 }
00730 }
00731
00732 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
00733 BOOST_UBLAS_INLINE
00734 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00735 typename self_type::
00736 #endif
00737 const_iterator2 begin () const {
00738 const self_type &m = (*this) ();
00739 return m.find2 (1, index1 (), 0);
00740 }
00741 BOOST_UBLAS_INLINE
00742 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00743 typename self_type::
00744 #endif
00745 const_iterator2 end () const {
00746 const self_type &m = (*this) ();
00747 return m.find2 (1, index1 (), m.size2 ());
00748 }
00749 BOOST_UBLAS_INLINE
00750 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00751 typename self_type::
00752 #endif
00753 const_reverse_iterator2 rbegin () const {
00754 return const_reverse_iterator2 (end ());
00755 }
00756 BOOST_UBLAS_INLINE
00757 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00758 typename self_type::
00759 #endif
00760 const_reverse_iterator2 rend () const {
00761 return const_reverse_iterator2 (begin ());
00762 }
00763 #endif
00764
00765
00766 BOOST_UBLAS_INLINE
00767 size_type index1 () const {
00768 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
00769 if (rank_ == 1) {
00770 const self_type &m = (*this) ();
00771 BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
00772 return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
00773 } else {
00774 return i_;
00775 }
00776 }
00777 BOOST_UBLAS_INLINE
00778 size_type index2 () const {
00779 if (rank_ == 1) {
00780 const self_type &m = (*this) ();
00781 BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
00782 return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
00783 } else {
00784 return j_;
00785 }
00786 }
00787
00788
00789 BOOST_UBLAS_INLINE
00790 const_iterator1 &operator = (const const_iterator1 &it) {
00791 container_const_reference<self_type>::assign (&it ());
00792 rank_ = it.rank_;
00793 i_ = it.i_;
00794 j_ = it.j_;
00795 it_ = it.it_;
00796 return *this;
00797 }
00798
00799
00800 BOOST_UBLAS_INLINE
00801 bool operator == (const const_iterator1 &it) const {
00802 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00803
00804 if (rank_ == 1 || it.rank_ == 1) {
00805 return it_ == it.it_;
00806 } else {
00807 return i_ == it.i_ && j_ == it.j_;
00808 }
00809 }
00810
00811 private:
00812 int rank_;
00813 size_type i_;
00814 size_type j_;
00815 const_subiterator_type it_;
00816 };
00817
00818 BOOST_UBLAS_INLINE
00819 const_iterator1 begin1 () const {
00820 return find1 (0, 0, 0);
00821 }
00822 BOOST_UBLAS_INLINE
00823 const_iterator1 end1 () const {
00824 return find1 (0, size1_, 0);
00825 }
00826
00827 class iterator1:
00828 public container_reference<mapped_matrix>,
00829 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
00830 iterator1, value_type> {
00831 public:
00832 typedef typename mapped_matrix::value_type value_type;
00833 typedef typename mapped_matrix::difference_type difference_type;
00834 typedef typename mapped_matrix::true_reference reference;
00835 typedef typename mapped_matrix::pointer pointer;
00836
00837 typedef iterator2 dual_iterator_type;
00838 typedef reverse_iterator2 dual_reverse_iterator_type;
00839
00840
00841 BOOST_UBLAS_INLINE
00842 iterator1 ():
00843 container_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
00844 BOOST_UBLAS_INLINE
00845 iterator1 (self_type &m, int rank, size_type i, size_type j, const subiterator_type &it):
00846 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
00847
00848
00849 BOOST_UBLAS_INLINE
00850 iterator1 &operator ++ () {
00851 if (rank_ == 1 && layout_type::fast_i ())
00852 ++ it_;
00853 else
00854 *this = (*this) ().find1 (rank_, index1 () + 1, j_, 1);
00855 return *this;
00856 }
00857 BOOST_UBLAS_INLINE
00858 iterator1 &operator -- () {
00859 if (rank_ == 1 && layout_type::fast_i ())
00860 -- it_;
00861 else
00862 *this = (*this) ().find1 (rank_, index1 () - 1, j_, -1);
00863 return *this;
00864 }
00865
00866
00867 BOOST_UBLAS_INLINE
00868 reference operator * () const {
00869 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
00870 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
00871 if (rank_ == 1) {
00872 return (*it_).second;
00873 } else {
00874 return (*this) ().at_element (i_, j_);
00875 }
00876 }
00877
00878 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
00879 BOOST_UBLAS_INLINE
00880 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00881 typename self_type::
00882 #endif
00883 iterator2 begin () const {
00884 self_type &m = (*this) ();
00885 return m.find2 (1, index1 (), 0);
00886 }
00887 BOOST_UBLAS_INLINE
00888 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00889 typename self_type::
00890 #endif
00891 iterator2 end () const {
00892 self_type &m = (*this) ();
00893 return m.find2 (1, index1 (), m.size2 ());
00894 }
00895 BOOST_UBLAS_INLINE
00896 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00897 typename self_type::
00898 #endif
00899 reverse_iterator2 rbegin () const {
00900 return reverse_iterator2 (end ());
00901 }
00902 BOOST_UBLAS_INLINE
00903 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00904 typename self_type::
00905 #endif
00906 reverse_iterator2 rend () const {
00907 return reverse_iterator2 (begin ());
00908 }
00909 #endif
00910
00911
00912 BOOST_UBLAS_INLINE
00913 size_type index1 () const {
00914 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
00915 if (rank_ == 1) {
00916 const self_type &m = (*this) ();
00917 BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
00918 return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
00919 } else {
00920 return i_;
00921 }
00922 }
00923 BOOST_UBLAS_INLINE
00924 size_type index2 () const {
00925 if (rank_ == 1) {
00926 const self_type &m = (*this) ();
00927 BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
00928 return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
00929 } else {
00930 return j_;
00931 }
00932 }
00933
00934
00935 BOOST_UBLAS_INLINE
00936 iterator1 &operator = (const iterator1 &it) {
00937 container_reference<self_type>::assign (&it ());
00938 rank_ = it.rank_;
00939 i_ = it.i_;
00940 j_ = it.j_;
00941 it_ = it.it_;
00942 return *this;
00943 }
00944
00945
00946 BOOST_UBLAS_INLINE
00947 bool operator == (const iterator1 &it) const {
00948 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00949
00950 if (rank_ == 1 || it.rank_ == 1) {
00951 return it_ == it.it_;
00952 } else {
00953 return i_ == it.i_ && j_ == it.j_;
00954 }
00955 }
00956
00957 private:
00958 int rank_;
00959 size_type i_;
00960 size_type j_;
00961 subiterator_type it_;
00962
00963 friend class const_iterator1;
00964 };
00965
00966 BOOST_UBLAS_INLINE
00967 iterator1 begin1 () {
00968 return find1 (0, 0, 0);
00969 }
00970 BOOST_UBLAS_INLINE
00971 iterator1 end1 () {
00972 return find1 (0, size1_, 0);
00973 }
00974
00975 class const_iterator2:
00976 public container_const_reference<mapped_matrix>,
00977 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
00978 const_iterator2, value_type> {
00979 public:
00980 typedef typename mapped_matrix::value_type value_type;
00981 typedef typename mapped_matrix::difference_type difference_type;
00982 typedef typename mapped_matrix::const_reference reference;
00983 typedef const typename mapped_matrix::pointer pointer;
00984
00985 typedef const_iterator1 dual_iterator_type;
00986 typedef const_reverse_iterator1 dual_reverse_iterator_type;
00987
00988
00989 BOOST_UBLAS_INLINE
00990 const_iterator2 ():
00991 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
00992 BOOST_UBLAS_INLINE
00993 const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_subiterator_type &it):
00994 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
00995 BOOST_UBLAS_INLINE
00996 const_iterator2 (const iterator2 &it):
00997 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
00998
00999
01000 BOOST_UBLAS_INLINE
01001 const_iterator2 &operator ++ () {
01002 if (rank_ == 1 && layout_type::fast_j ())
01003 ++ it_;
01004 else
01005 *this = (*this) ().find2 (rank_, i_, index2 () + 1, 1);
01006 return *this;
01007 }
01008 BOOST_UBLAS_INLINE
01009 const_iterator2 &operator -- () {
01010 if (rank_ == 1 && layout_type::fast_j ())
01011 -- it_;
01012 else
01013 *this = (*this) ().find2 (rank_, i_, index2 () - 1, -1);
01014 return *this;
01015 }
01016
01017
01018 BOOST_UBLAS_INLINE
01019 const_reference operator * () const {
01020 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
01021 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
01022 if (rank_ == 1) {
01023 return (*it_).second;
01024 } else {
01025 return (*this) () (i_, j_);
01026 }
01027 }
01028
01029 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
01030 BOOST_UBLAS_INLINE
01031 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01032 typename self_type::
01033 #endif
01034 const_iterator1 begin () const {
01035 const self_type &m = (*this) ();
01036 return m.find1 (1, 0, index2 ());
01037 }
01038 BOOST_UBLAS_INLINE
01039 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01040 typename self_type::
01041 #endif
01042 const_iterator1 end () const {
01043 const self_type &m = (*this) ();
01044 return m.find1 (1, m.size1 (), index2 ());
01045 }
01046 BOOST_UBLAS_INLINE
01047 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01048 typename self_type::
01049 #endif
01050 const_reverse_iterator1 rbegin () const {
01051 return const_reverse_iterator1 (end ());
01052 }
01053 BOOST_UBLAS_INLINE
01054 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01055 typename self_type::
01056 #endif
01057 const_reverse_iterator1 rend () const {
01058 return const_reverse_iterator1 (begin ());
01059 }
01060 #endif
01061
01062
01063 BOOST_UBLAS_INLINE
01064 size_type index1 () const {
01065 if (rank_ == 1) {
01066 const self_type &m = (*this) ();
01067 BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
01068 return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
01069 } else {
01070 return i_;
01071 }
01072 }
01073 BOOST_UBLAS_INLINE
01074 size_type index2 () const {
01075 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
01076 if (rank_ == 1) {
01077 const self_type &m = (*this) ();
01078 BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
01079 return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
01080 } else {
01081 return j_;
01082 }
01083 }
01084
01085
01086 BOOST_UBLAS_INLINE
01087 const_iterator2 &operator = (const const_iterator2 &it) {
01088 container_const_reference<self_type>::assign (&it ());
01089 rank_ = it.rank_;
01090 i_ = it.i_;
01091 j_ = it.j_;
01092 it_ = it.it_;
01093 return *this;
01094 }
01095
01096
01097 BOOST_UBLAS_INLINE
01098 bool operator == (const const_iterator2 &it) const {
01099 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01100
01101 if (rank_ == 1 || it.rank_ == 1) {
01102 return it_ == it.it_;
01103 } else {
01104 return i_ == it.i_ && j_ == it.j_;
01105 }
01106 }
01107
01108 private:
01109 int rank_;
01110 size_type i_;
01111 size_type j_;
01112 const_subiterator_type it_;
01113 };
01114
01115 BOOST_UBLAS_INLINE
01116 const_iterator2 begin2 () const {
01117 return find2 (0, 0, 0);
01118 }
01119 BOOST_UBLAS_INLINE
01120 const_iterator2 end2 () const {
01121 return find2 (0, 0, size2_);
01122 }
01123
01124 class iterator2:
01125 public container_reference<mapped_matrix>,
01126 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
01127 iterator2, value_type> {
01128 public:
01129 typedef typename mapped_matrix::value_type value_type;
01130 typedef typename mapped_matrix::difference_type difference_type;
01131 typedef typename mapped_matrix::true_reference reference;
01132 typedef typename mapped_matrix::pointer pointer;
01133
01134 typedef iterator1 dual_iterator_type;
01135 typedef reverse_iterator1 dual_reverse_iterator_type;
01136
01137
01138 BOOST_UBLAS_INLINE
01139 iterator2 ():
01140 container_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
01141 BOOST_UBLAS_INLINE
01142 iterator2 (self_type &m, int rank, size_type i, size_type j, const subiterator_type &it):
01143 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
01144
01145
01146 BOOST_UBLAS_INLINE
01147 iterator2 &operator ++ () {
01148 if (rank_ == 1 && layout_type::fast_j ())
01149 ++ it_;
01150 else
01151 *this = (*this) ().find2 (rank_, i_, index2 () + 1, 1);
01152 return *this;
01153 }
01154 BOOST_UBLAS_INLINE
01155 iterator2 &operator -- () {
01156 if (rank_ == 1 && layout_type::fast_j ())
01157 -- it_;
01158 else
01159 *this = (*this) ().find2 (rank_, i_, index2 () - 1, -1);
01160 return *this;
01161 }
01162
01163
01164 BOOST_UBLAS_INLINE
01165 reference operator * () const {
01166 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
01167 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
01168 if (rank_ == 1) {
01169 return (*it_).second;
01170 } else {
01171 return (*this) ().at_element (i_, j_);
01172 }
01173 }
01174
01175 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
01176 BOOST_UBLAS_INLINE
01177 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01178 typename self_type::
01179 #endif
01180 iterator1 begin () const {
01181 self_type &m = (*this) ();
01182 return m.find1 (1, 0, index2 ());
01183 }
01184 BOOST_UBLAS_INLINE
01185 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01186 typename self_type::
01187 #endif
01188 iterator1 end () const {
01189 self_type &m = (*this) ();
01190 return m.find1 (1, m.size1 (), index2 ());
01191 }
01192 BOOST_UBLAS_INLINE
01193 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01194 typename self_type::
01195 #endif
01196 reverse_iterator1 rbegin () const {
01197 return reverse_iterator1 (end ());
01198 }
01199 BOOST_UBLAS_INLINE
01200 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01201 typename self_type::
01202 #endif
01203 reverse_iterator1 rend () const {
01204 return reverse_iterator1 (begin ());
01205 }
01206 #endif
01207
01208
01209 BOOST_UBLAS_INLINE
01210 size_type index1 () const {
01211 if (rank_ == 1) {
01212 const self_type &m = (*this) ();
01213 BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
01214 return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
01215 } else {
01216 return i_;
01217 }
01218 }
01219 BOOST_UBLAS_INLINE
01220 size_type index2 () const {
01221 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
01222 if (rank_ == 1) {
01223 const self_type &m = (*this) ();
01224 BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
01225 return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
01226 } else {
01227 return j_;
01228 }
01229 }
01230
01231
01232 BOOST_UBLAS_INLINE
01233 iterator2 &operator = (const iterator2 &it) {
01234 container_reference<self_type>::assign (&it ());
01235 rank_ = it.rank_;
01236 i_ = it.i_;
01237 j_ = it.j_;
01238 it_ = it.it_;
01239 return *this;
01240 }
01241
01242
01243 BOOST_UBLAS_INLINE
01244 bool operator == (const iterator2 &it) const {
01245 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01246
01247 if (rank_ == 1 || it.rank_ == 1) {
01248 return it_ == it.it_;
01249 } else {
01250 return i_ == it.i_ && j_ == it.j_;
01251 }
01252 }
01253
01254 private:
01255 int rank_;
01256 size_type i_;
01257 size_type j_;
01258 subiterator_type it_;
01259
01260 friend class const_iterator2;
01261 };
01262
01263 BOOST_UBLAS_INLINE
01264 iterator2 begin2 () {
01265 return find2 (0, 0, 0);
01266 }
01267 BOOST_UBLAS_INLINE
01268 iterator2 end2 () {
01269 return find2 (0, 0, size2_);
01270 }
01271
01272
01273
01274 BOOST_UBLAS_INLINE
01275 const_reverse_iterator1 rbegin1 () const {
01276 return const_reverse_iterator1 (end1 ());
01277 }
01278 BOOST_UBLAS_INLINE
01279 const_reverse_iterator1 rend1 () const {
01280 return const_reverse_iterator1 (begin1 ());
01281 }
01282
01283 BOOST_UBLAS_INLINE
01284 reverse_iterator1 rbegin1 () {
01285 return reverse_iterator1 (end1 ());
01286 }
01287 BOOST_UBLAS_INLINE
01288 reverse_iterator1 rend1 () {
01289 return reverse_iterator1 (begin1 ());
01290 }
01291
01292 BOOST_UBLAS_INLINE
01293 const_reverse_iterator2 rbegin2 () const {
01294 return const_reverse_iterator2 (end2 ());
01295 }
01296 BOOST_UBLAS_INLINE
01297 const_reverse_iterator2 rend2 () const {
01298 return const_reverse_iterator2 (begin2 ());
01299 }
01300
01301 BOOST_UBLAS_INLINE
01302 reverse_iterator2 rbegin2 () {
01303 return reverse_iterator2 (end2 ());
01304 }
01305 BOOST_UBLAS_INLINE
01306 reverse_iterator2 rend2 () {
01307 return reverse_iterator2 (begin2 ());
01308 }
01309
01310
01311 template<class Archive>
01312 void serialize(Archive & ar, const unsigned int ){
01313 serialization::collection_size_type s1 (size1_);
01314 serialization::collection_size_type s2 (size2_);
01315 ar & serialization::make_nvp("size1",s1);
01316 ar & serialization::make_nvp("size2",s2);
01317 if (Archive::is_loading::value) {
01318 size1_ = s1;
01319 size2_ = s2;
01320 }
01321 ar & serialization::make_nvp("data", data_);
01322 }
01323
01324 private:
01325 size_type size1_;
01326 size_type size2_;
01327 array_type data_;
01328 static const value_type zero_;
01329 };
01330
01331 template<class T, class L, class A>
01332 const typename mapped_matrix<T, L, A>::value_type mapped_matrix<T, L, A>::zero_ = value_type();
01333
01334
01335
01336 template<class T, class L, class A>
01337 class mapped_vector_of_mapped_vector:
01338 public matrix_container<mapped_vector_of_mapped_vector<T, L, A> > {
01339
01340 typedef T &true_reference;
01341 typedef T *pointer;
01342 typedef const T *const_pointer;
01343 typedef A array_type;
01344 typedef const A const_array_type;
01345 typedef L layout_type;
01346 typedef mapped_vector_of_mapped_vector<T, L, A> self_type;
01347 public:
01348 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
01349 using matrix_container<self_type>::operator ();
01350 #endif
01351 typedef typename A::size_type size_type;
01352 typedef typename A::difference_type difference_type;
01353 typedef T value_type;
01354 typedef const T &const_reference;
01355 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
01356 typedef typename detail::map_traits<typename A::data_value_type, T>::reference reference;
01357 #else
01358 typedef sparse_matrix_element<self_type> reference;
01359 #endif
01360 typedef const matrix_reference<const self_type> const_closure_type;
01361 typedef matrix_reference<self_type> closure_type;
01362 typedef mapped_vector<T, typename A::value_type> vector_temporary_type;
01363 typedef self_type matrix_temporary_type;
01364 typedef typename A::value_type::second_type vector_data_value_type;
01365 typedef sparse_tag storage_category;
01366 typedef typename L::orientation_category orientation_category;
01367
01368
01369 BOOST_UBLAS_INLINE
01370 mapped_vector_of_mapped_vector ():
01371 matrix_container<self_type> (),
01372 size1_ (0), size2_ (0), data_ () {
01373 data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
01374 }
01375 BOOST_UBLAS_INLINE
01376 mapped_vector_of_mapped_vector (size_type size1, size_type size2, size_type non_zeros = 0):
01377 matrix_container<self_type> (),
01378 size1_ (size1), size2_ (size2), data_ () {
01379 data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
01380 }
01381 BOOST_UBLAS_INLINE
01382 mapped_vector_of_mapped_vector (const mapped_vector_of_mapped_vector &m):
01383 matrix_container<self_type> (),
01384 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
01385 template<class AE>
01386 BOOST_UBLAS_INLINE
01387 mapped_vector_of_mapped_vector (const matrix_expression<AE> &ae, size_type non_zeros = 0):
01388 matrix_container<self_type> (),
01389 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () {
01390 data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
01391 matrix_assign<scalar_assign> (*this, ae);
01392 }
01393
01394
01395 BOOST_UBLAS_INLINE
01396 size_type size1 () const {
01397 return size1_;
01398 }
01399 BOOST_UBLAS_INLINE
01400 size_type size2 () const {
01401 return size2_;
01402 }
01403 BOOST_UBLAS_INLINE
01404 size_type nnz_capacity () const {
01405 size_type non_zeros = 0;
01406 for (vector_const_subiterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv)
01407 non_zeros += detail::map_capacity (*itv);
01408 return non_zeros;
01409 }
01410 BOOST_UBLAS_INLINE
01411 size_type nnz () const {
01412 size_type filled = 0;
01413 for (vector_const_subiterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv)
01414 filled += (*itv).size ();
01415 return filled;
01416 }
01417
01418
01419 BOOST_UBLAS_INLINE
01420 const_array_type &data () const {
01421 return data_;
01422 }
01423 BOOST_UBLAS_INLINE
01424 array_type &data () {
01425 return data_;
01426 }
01427
01428
01429 BOOST_UBLAS_INLINE
01430 void resize (size_type size1, size_type size2, bool preserve = true) {
01431
01432 BOOST_UBLAS_CHECK (!preserve, internal_logic ());
01433 size1_ = size1;
01434 size2_ = size2;
01435 data ().clear ();
01436 data () [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
01437 }
01438
01439
01440 BOOST_UBLAS_INLINE
01441 pointer find_element (size_type i, size_type j) {
01442 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
01443 }
01444 BOOST_UBLAS_INLINE
01445 const_pointer find_element (size_type i, size_type j) const {
01446 const size_type element1 = layout_type::index_M (i, j);
01447 const size_type element2 = layout_type::index_m (i, j);
01448 vector_const_subiterator_type itv (data ().find (element1));
01449 if (itv == data ().end ())
01450 return 0;
01451 BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ());
01452 const_subiterator_type it ((*itv).second.find (element2));
01453 if (it == (*itv).second.end ())
01454 return 0;
01455 BOOST_UBLAS_CHECK ((*it).first == element2, internal_logic ());
01456 return &(*it).second;
01457 }
01458
01459
01460 BOOST_UBLAS_INLINE
01461 const_reference operator () (size_type i, size_type j) const {
01462 const size_type element1 = layout_type::index_M (i, j);
01463 const size_type element2 = layout_type::index_m (i, j);
01464 vector_const_subiterator_type itv (data ().find (element1));
01465 if (itv == data ().end ())
01466 return zero_;
01467 BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ());
01468 const_subiterator_type it ((*itv).second.find (element2));
01469 if (it == (*itv).second.end ())
01470 return zero_;
01471 BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ());
01472 return (*it).second;
01473 }
01474 BOOST_UBLAS_INLINE
01475 reference operator () (size_type i, size_type j) {
01476 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
01477 const size_type element1 = layout_type::index_M (i, j);
01478 const size_type element2 = layout_type::index_m (i, j);
01479 vector_data_value_type& vd (data () [element1]);
01480 std::pair<subiterator_type, bool> ii (vd.insert (typename array_type::value_type::second_type::value_type (element2, value_type())));
01481 BOOST_UBLAS_CHECK ((ii.first)->first == element2, internal_logic ());
01482 return (ii.first)->second;
01483 #else
01484 return reference (*this, i, j);
01485 #endif
01486 }
01487
01488
01489 BOOST_UBLAS_INLINE
01490 true_reference insert_element (size_type i, size_type j, const_reference t) {
01491 BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ());
01492 const size_type element1 = layout_type::index_M (i, j);
01493 const size_type element2 = layout_type::index_m (i, j);
01494
01495 vector_data_value_type& vd (data () [element1]);
01496 std::pair<subiterator_type, bool> ii (vd.insert (typename vector_data_value_type::value_type (element2, t)));
01497 BOOST_UBLAS_CHECK ((ii.first)->first == element2, internal_logic ());
01498 if (!ii.second)
01499 (ii.first)->second = t;
01500 return (ii.first)->second;
01501 }
01502 BOOST_UBLAS_INLINE
01503 void erase_element (size_type i, size_type j) {
01504 vector_subiterator_type itv (data ().find (layout_type::index_M (i, j)));
01505 if (itv == data ().end ())
01506 return;
01507 subiterator_type it ((*itv).second.find (layout_type::index_m (i, j)));
01508 if (it == (*itv).second.end ())
01509 return;
01510 (*itv).second.erase (it);
01511 }
01512
01513
01514 BOOST_UBLAS_INLINE
01515 void clear () {
01516 data ().clear ();
01517 data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
01518 }
01519
01520
01521 BOOST_UBLAS_INLINE
01522 mapped_vector_of_mapped_vector &operator = (const mapped_vector_of_mapped_vector &m) {
01523 if (this != &m) {
01524 size1_ = m.size1_;
01525 size2_ = m.size2_;
01526 data () = m.data ();
01527 }
01528 return *this;
01529 }
01530 template<class C>
01531 BOOST_UBLAS_INLINE
01532 mapped_vector_of_mapped_vector &operator = (const matrix_container<C> &m) {
01533 resize (m ().size1 (), m ().size2 ());
01534 assign (m);
01535 return *this;
01536 }
01537 BOOST_UBLAS_INLINE
01538 mapped_vector_of_mapped_vector &assign_temporary (mapped_vector_of_mapped_vector &m) {
01539 swap (m);
01540 return *this;
01541 }
01542 template<class AE>
01543 BOOST_UBLAS_INLINE
01544 mapped_vector_of_mapped_vector &operator = (const matrix_expression<AE> &ae) {
01545 self_type temporary (ae);
01546 return assign_temporary (temporary);
01547 }
01548 template<class AE>
01549 BOOST_UBLAS_INLINE
01550 mapped_vector_of_mapped_vector &assign (const matrix_expression<AE> &ae) {
01551 matrix_assign<scalar_assign> (*this, ae);
01552 return *this;
01553 }
01554 template<class AE>
01555 BOOST_UBLAS_INLINE
01556 mapped_vector_of_mapped_vector& operator += (const matrix_expression<AE> &ae) {
01557 self_type temporary (*this + ae);
01558 return assign_temporary (temporary);
01559 }
01560 template<class C>
01561 BOOST_UBLAS_INLINE
01562 mapped_vector_of_mapped_vector &operator += (const matrix_container<C> &m) {
01563 plus_assign (m);
01564 return *this;
01565 }
01566 template<class AE>
01567 BOOST_UBLAS_INLINE
01568 mapped_vector_of_mapped_vector &plus_assign (const matrix_expression<AE> &ae) {
01569 matrix_assign<scalar_plus_assign> (*this, ae);
01570 return *this;
01571 }
01572 template<class AE>
01573 BOOST_UBLAS_INLINE
01574 mapped_vector_of_mapped_vector& operator -= (const matrix_expression<AE> &ae) {
01575 self_type temporary (*this - ae);
01576 return assign_temporary (temporary);
01577 }
01578 template<class C>
01579 BOOST_UBLAS_INLINE
01580 mapped_vector_of_mapped_vector &operator -= (const matrix_container<C> &m) {
01581 minus_assign (m);
01582 return *this;
01583 }
01584 template<class AE>
01585 BOOST_UBLAS_INLINE
01586 mapped_vector_of_mapped_vector &minus_assign (const matrix_expression<AE> &ae) {
01587 matrix_assign<scalar_minus_assign> (*this, ae);
01588 return *this;
01589 }
01590 template<class AT>
01591 BOOST_UBLAS_INLINE
01592 mapped_vector_of_mapped_vector& operator *= (const AT &at) {
01593 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
01594 return *this;
01595 }
01596 template<class AT>
01597 BOOST_UBLAS_INLINE
01598 mapped_vector_of_mapped_vector& operator /= (const AT &at) {
01599 matrix_assign_scalar<scalar_divides_assign> (*this, at);
01600 return *this;
01601 }
01602
01603
01604 BOOST_UBLAS_INLINE
01605 void swap (mapped_vector_of_mapped_vector &m) {
01606 if (this != &m) {
01607 std::swap (size1_, m.size1_);
01608 std::swap (size2_, m.size2_);
01609 data ().swap (m.data ());
01610 }
01611 }
01612 BOOST_UBLAS_INLINE
01613 friend void swap (mapped_vector_of_mapped_vector &m1, mapped_vector_of_mapped_vector &m2) {
01614 m1.swap (m2);
01615 }
01616
01617
01618 private:
01619
01620 typedef typename A::const_iterator vector_const_subiterator_type;
01621 typedef typename A::iterator vector_subiterator_type;
01622 typedef typename A::value_type::second_type::const_iterator const_subiterator_type;
01623 typedef typename A::value_type::second_type::iterator subiterator_type;
01624
01625 BOOST_UBLAS_INLINE
01626 true_reference at_element (size_type i, size_type j) {
01627 const size_type element1 = layout_type::index_M (i, j);
01628 const size_type element2 = layout_type::index_m (i, j);
01629 vector_subiterator_type itv (data ().find (element1));
01630 BOOST_UBLAS_CHECK (itv != data ().end(), bad_index ());
01631 BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ());
01632 subiterator_type it ((*itv).second.find (element2));
01633 BOOST_UBLAS_CHECK (it != (*itv).second.end (), bad_index ());
01634 BOOST_UBLAS_CHECK ((*it).first == element2, internal_logic ());
01635
01636 return it->second;
01637 }
01638
01639 public:
01640 class const_iterator1;
01641 class iterator1;
01642 class const_iterator2;
01643 class iterator2;
01644 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
01645 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
01646 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
01647 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
01648
01649
01650
01651 const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
01652 BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
01653 for (;;) {
01654 vector_const_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
01655 vector_const_subiterator_type itv_end (data ().end ());
01656 if (itv == itv_end)
01657 return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
01658
01659 const_subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
01660 const_subiterator_type it_end ((*itv).second.end ());
01661 if (rank == 0) {
01662
01663 size_type M = itv->first;
01664 size_type m;
01665 if (it != it_end) {
01666 m = it->first;
01667 } else {
01668 m = layout_type::size_m(size1_, size2_);
01669 }
01670 size_type first_i = layout_type::index_M(M,m);
01671 return const_iterator1 (*this, rank, first_i, j, itv, it);
01672 }
01673 if (it != it_end && (*it).first == layout_type::index_m (i, j))
01674 return const_iterator1 (*this, rank, i, j, itv, it);
01675 if (direction > 0) {
01676 if (layout_type::fast_i ()) {
01677 if (it == it_end)
01678 return const_iterator1 (*this, rank, i, j, itv, it);
01679 i = (*it).first;
01680 } else {
01681 if (i >= size1_)
01682 return const_iterator1 (*this, rank, i, j, itv, it);
01683 ++ i;
01684 }
01685 } else {
01686 if (layout_type::fast_i ()) {
01687 if (it == (*itv).second.begin ())
01688 return const_iterator1 (*this, rank, i, j, itv, it);
01689 -- it;
01690 i = (*it).first;
01691 } else {
01692 if (i == 0)
01693 return const_iterator1 (*this, rank, i, j, itv, it);
01694 -- i;
01695 }
01696 }
01697 }
01698 }
01699
01700 iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
01701 BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
01702 for (;;) {
01703 vector_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
01704 vector_subiterator_type itv_end (data ().end ());
01705 if (itv == itv_end)
01706 return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
01707
01708 subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
01709 subiterator_type it_end ((*itv).second.end ());
01710 if (rank == 0) {
01711
01712 size_type M = itv->first;
01713 size_type m;
01714 if (it != it_end) {
01715 m = it->first;
01716 } else {
01717 m = layout_type::size_m(size1_, size2_);
01718 }
01719 size_type first_i = layout_type::index_M(M,m);
01720 return iterator1 (*this, rank, first_i, j, itv, it);
01721 }
01722 if (it != it_end && (*it).first == layout_type::index_m (i, j))
01723 return iterator1 (*this, rank, i, j, itv, it);
01724 if (direction > 0) {
01725 if (layout_type::fast_i ()) {
01726 if (it == it_end)
01727 return iterator1 (*this, rank, i, j, itv, it);
01728 i = (*it).first;
01729 } else {
01730 if (i >= size1_)
01731 return iterator1 (*this, rank, i, j, itv, it);
01732 ++ i;
01733 }
01734 } else {
01735 if (layout_type::fast_i ()) {
01736 if (it == (*itv).second.begin ())
01737 return iterator1 (*this, rank, i, j, itv, it);
01738 -- it;
01739 i = (*it).first;
01740 } else {
01741 if (i == 0)
01742 return iterator1 (*this, rank, i, j, itv, it);
01743 -- i;
01744 }
01745 }
01746 }
01747 }
01748
01749 const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
01750 BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
01751 for (;;) {
01752 vector_const_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
01753 vector_const_subiterator_type itv_end (data ().end ());
01754 if (itv == itv_end)
01755 return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
01756
01757 const_subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
01758 const_subiterator_type it_end ((*itv).second.end ());
01759 if (rank == 0) {
01760
01761 size_type M = itv->first;
01762 size_type m;
01763 if (it != it_end) {
01764 m = it->first;
01765 } else {
01766 m = layout_type::size_m(size1_, size2_);
01767 }
01768 size_type first_j = layout_type::index_m(M,m);
01769 return const_iterator2 (*this, rank, i, first_j, itv, it);
01770 }
01771 if (it != it_end && (*it).first == layout_type::index_m (i, j))
01772 return const_iterator2 (*this, rank, i, j, itv, it);
01773 if (direction > 0) {
01774 if (layout_type::fast_j ()) {
01775 if (it == it_end)
01776 return const_iterator2 (*this, rank, i, j, itv, it);
01777 j = (*it).first;
01778 } else {
01779 if (j >= size2_)
01780 return const_iterator2 (*this, rank, i, j, itv, it);
01781 ++ j;
01782 }
01783 } else {
01784 if (layout_type::fast_j ()) {
01785 if (it == (*itv).second.begin ())
01786 return const_iterator2 (*this, rank, i, j, itv, it);
01787 -- it;
01788 j = (*it).first;
01789 } else {
01790 if (j == 0)
01791 return const_iterator2 (*this, rank, i, j, itv, it);
01792 -- j;
01793 }
01794 }
01795 }
01796 }
01797
01798 iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
01799 BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
01800 for (;;) {
01801 vector_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
01802 vector_subiterator_type itv_end (data ().end ());
01803 if (itv == itv_end)
01804 return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
01805
01806 subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
01807 subiterator_type it_end ((*itv).second.end ());
01808 if (rank == 0) {
01809
01810 size_type M = itv->first;
01811 size_type m;
01812 if (it != it_end) {
01813 m = it->first;
01814 } else {
01815 m = layout_type::size_m(size1_, size2_);
01816 }
01817 size_type first_j = layout_type::index_m(M,m);
01818 return iterator2 (*this, rank, i, first_j, itv, it);
01819 }
01820 if (it != it_end && (*it).first == layout_type::index_m (i, j))
01821 return iterator2 (*this, rank, i, j, itv, it);
01822 if (direction > 0) {
01823 if (layout_type::fast_j ()) {
01824 if (it == it_end)
01825 return iterator2 (*this, rank, i, j, itv, it);
01826 j = (*it).first;
01827 } else {
01828 if (j >= size2_)
01829 return iterator2 (*this, rank, i, j, itv, it);
01830 ++ j;
01831 }
01832 } else {
01833 if (layout_type::fast_j ()) {
01834 if (it == (*itv).second.begin ())
01835 return iterator2 (*this, rank, i, j, itv, it);
01836 -- it;
01837 j = (*it).first;
01838 } else {
01839 if (j == 0)
01840 return iterator2 (*this, rank, i, j, itv, it);
01841 -- j;
01842 }
01843 }
01844 }
01845 }
01846
01847 class const_iterator1:
01848 public container_const_reference<mapped_vector_of_mapped_vector>,
01849 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
01850 const_iterator1, value_type> {
01851 public:
01852 typedef typename mapped_vector_of_mapped_vector::value_type value_type;
01853 typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
01854 typedef typename mapped_vector_of_mapped_vector::const_reference reference;
01855 typedef const typename mapped_vector_of_mapped_vector::pointer pointer;
01856
01857 typedef const_iterator2 dual_iterator_type;
01858 typedef const_reverse_iterator2 dual_reverse_iterator_type;
01859
01860
01861 BOOST_UBLAS_INLINE
01862 const_iterator1 ():
01863 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
01864 BOOST_UBLAS_INLINE
01865 const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it):
01866 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
01867 BOOST_UBLAS_INLINE
01868 const_iterator1 (const iterator1 &it):
01869 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
01870
01871
01872 BOOST_UBLAS_INLINE
01873 const_iterator1 &operator ++ () {
01874 if (rank_ == 1 && layout_type::fast_i ())
01875 ++ it_;
01876 else {
01877 const self_type &m = (*this) ();
01878 if (rank_ == 0) {
01879 ++ itv_;
01880 i_ = itv_->first;
01881 } else {
01882 i_ = index1 () + 1;
01883 }
01884 if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
01885 *this = m.find1 (rank_, i_, j_, 1);
01886 else if (rank_ == 1) {
01887 it_ = (*itv_).second.begin ();
01888 if (it_ == (*itv_).second.end () || index2 () != j_)
01889 *this = m.find1 (rank_, i_, j_, 1);
01890 }
01891 }
01892 return *this;
01893 }
01894 BOOST_UBLAS_INLINE
01895 const_iterator1 &operator -- () {
01896 if (rank_ == 1 && layout_type::fast_i ())
01897 -- it_;
01898 else {
01899 const self_type &m = (*this) ();
01900 if (rank_ == 0) {
01901 -- itv_;
01902 i_ = itv_->first;
01903 } else {
01904 i_ = index1 () - 1;
01905 }
01906
01907 if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
01908 *this = m.find1 (rank_, i_, j_, -1);
01909 else if (rank_ == 1) {
01910 it_ = (*itv_).second.begin ();
01911 if (it_ == (*itv_).second.end () || index2 () != j_)
01912 *this = m.find1 (rank_, i_, j_, -1);
01913 }
01914 }
01915 return *this;
01916 }
01917
01918
01919 BOOST_UBLAS_INLINE
01920 const_reference operator * () const {
01921 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
01922 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
01923 if (rank_ == 1) {
01924 return (*it_).second;
01925 } else {
01926 return (*this) () (i_, j_);
01927 }
01928 }
01929
01930 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
01931 BOOST_UBLAS_INLINE
01932 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01933 typename self_type::
01934 #endif
01935 const_iterator2 begin () const {
01936 const self_type &m = (*this) ();
01937 return m.find2 (1, index1 (), 0);
01938 }
01939 BOOST_UBLAS_INLINE
01940 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01941 typename self_type::
01942 #endif
01943 const_iterator2 end () const {
01944 const self_type &m = (*this) ();
01945 return m.find2 (1, index1 (), m.size2 ());
01946 }
01947 BOOST_UBLAS_INLINE
01948 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01949 typename self_type::
01950 #endif
01951 const_reverse_iterator2 rbegin () const {
01952 return const_reverse_iterator2 (end ());
01953 }
01954 BOOST_UBLAS_INLINE
01955 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01956 typename self_type::
01957 #endif
01958 const_reverse_iterator2 rend () const {
01959 return const_reverse_iterator2 (begin ());
01960 }
01961 #endif
01962
01963
01964 BOOST_UBLAS_INLINE
01965 size_type index1 () const {
01966 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
01967 if (rank_ == 1) {
01968 BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
01969 return layout_type::index_M ((*itv_).first, (*it_).first);
01970 } else {
01971 return i_;
01972 }
01973 }
01974 BOOST_UBLAS_INLINE
01975 size_type index2 () const {
01976 if (rank_ == 1) {
01977 BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
01978 return layout_type::index_m ((*itv_).first, (*it_).first);
01979 } else {
01980 return j_;
01981 }
01982 }
01983
01984
01985 BOOST_UBLAS_INLINE
01986 const_iterator1 &operator = (const const_iterator1 &it) {
01987 container_const_reference<self_type>::assign (&it ());
01988 rank_ = it.rank_;
01989 i_ = it.i_;
01990 j_ = it.j_;
01991 itv_ = it.itv_;
01992 it_ = it.it_;
01993 return *this;
01994 }
01995
01996
01997 BOOST_UBLAS_INLINE
01998 bool operator == (const const_iterator1 &it) const {
01999 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
02000
02001 if (rank_ == 1 || it.rank_ == 1) {
02002 return it_ == it.it_;
02003 } else {
02004 return i_ == it.i_ && j_ == it.j_;
02005 }
02006 }
02007
02008 private:
02009 int rank_;
02010 size_type i_;
02011 size_type j_;
02012 vector_const_subiterator_type itv_;
02013 const_subiterator_type it_;
02014 };
02015
02016 BOOST_UBLAS_INLINE
02017 const_iterator1 begin1 () const {
02018 return find1 (0, 0, 0);
02019 }
02020 BOOST_UBLAS_INLINE
02021 const_iterator1 end1 () const {
02022 return find1 (0, size1_, 0);
02023 }
02024
02025 class iterator1:
02026 public container_reference<mapped_vector_of_mapped_vector>,
02027 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
02028 iterator1, value_type> {
02029 public:
02030 typedef typename mapped_vector_of_mapped_vector::value_type value_type;
02031 typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
02032 typedef typename mapped_vector_of_mapped_vector::true_reference reference;
02033 typedef typename mapped_vector_of_mapped_vector::pointer pointer;
02034
02035 typedef iterator2 dual_iterator_type;
02036 typedef reverse_iterator2 dual_reverse_iterator_type;
02037
02038
02039 BOOST_UBLAS_INLINE
02040 iterator1 ():
02041 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
02042 BOOST_UBLAS_INLINE
02043 iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
02044 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
02045
02046
02047 BOOST_UBLAS_INLINE
02048 iterator1 &operator ++ () {
02049 if (rank_ == 1 && layout_type::fast_i ())
02050 ++ it_;
02051 else {
02052 self_type &m = (*this) ();
02053 if (rank_ == 0) {
02054 ++ itv_;
02055 i_ = itv_->first;
02056 } else {
02057 i_ = index1 () + 1;
02058 }
02059 if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
02060 *this = m.find1 (rank_, i_, j_, 1);
02061 else if (rank_ == 1) {
02062 it_ = (*itv_).second.begin ();
02063 if (it_ == (*itv_).second.end () || index2 () != j_)
02064 *this = m.find1 (rank_, i_, j_, 1);
02065 }
02066 }
02067 return *this;
02068 }
02069 BOOST_UBLAS_INLINE
02070 iterator1 &operator -- () {
02071 if (rank_ == 1 && layout_type::fast_i ())
02072 -- it_;
02073 else {
02074 self_type &m = (*this) ();
02075 if (rank_ == 0) {
02076 -- itv_;
02077 i_ = itv_->first;
02078 } else {
02079 i_ = index1 () - 1;
02080 }
02081
02082 if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
02083 *this = m.find1 (rank_, i_, j_, -1);
02084 else if (rank_ == 1) {
02085 it_ = (*itv_).second.begin ();
02086 if (it_ == (*itv_).second.end () || index2 () != j_)
02087 *this = m.find1 (rank_, i_, j_, -1);
02088 }
02089 }
02090 return *this;
02091 }
02092
02093
02094 BOOST_UBLAS_INLINE
02095 reference operator * () const {
02096 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
02097 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
02098 if (rank_ == 1) {
02099 return (*it_).second;
02100 } else {
02101 return (*this) ().at_element (i_, j_);
02102 }
02103 }
02104
02105 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
02106 BOOST_UBLAS_INLINE
02107 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02108 typename self_type::
02109 #endif
02110 iterator2 begin () const {
02111 self_type &m = (*this) ();
02112 return m.find2 (1, index1 (), 0);
02113 }
02114 BOOST_UBLAS_INLINE
02115 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02116 typename self_type::
02117 #endif
02118 iterator2 end () const {
02119 self_type &m = (*this) ();
02120 return m.find2 (1, index1 (), m.size2 ());
02121 }
02122 BOOST_UBLAS_INLINE
02123 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02124 typename self_type::
02125 #endif
02126 reverse_iterator2 rbegin () const {
02127 return reverse_iterator2 (end ());
02128 }
02129 BOOST_UBLAS_INLINE
02130 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02131 typename self_type::
02132 #endif
02133 reverse_iterator2 rend () const {
02134 return reverse_iterator2 (begin ());
02135 }
02136 #endif
02137
02138
02139 BOOST_UBLAS_INLINE
02140 size_type index1 () const {
02141 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
02142 if (rank_ == 1) {
02143 BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
02144 return layout_type::index_M ((*itv_).first, (*it_).first);
02145 } else {
02146 return i_;
02147 }
02148 }
02149 BOOST_UBLAS_INLINE
02150 size_type index2 () const {
02151 if (rank_ == 1) {
02152 BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
02153 return layout_type::index_m ((*itv_).first, (*it_).first);
02154 } else {
02155 return j_;
02156 }
02157 }
02158
02159
02160 BOOST_UBLAS_INLINE
02161 iterator1 &operator = (const iterator1 &it) {
02162 container_reference<self_type>::assign (&it ());
02163 rank_ = it.rank_;
02164 i_ = it.i_;
02165 j_ = it.j_;
02166 itv_ = it.itv_;
02167 it_ = it.it_;
02168 return *this;
02169 }
02170
02171
02172 BOOST_UBLAS_INLINE
02173 bool operator == (const iterator1 &it) const {
02174 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
02175
02176 if (rank_ == 1 || it.rank_ == 1) {
02177 return it_ == it.it_;
02178 } else {
02179 return i_ == it.i_ && j_ == it.j_;
02180 }
02181 }
02182
02183 private:
02184 int rank_;
02185 size_type i_;
02186 size_type j_;
02187 vector_subiterator_type itv_;
02188 subiterator_type it_;
02189
02190 friend class const_iterator1;
02191 };
02192
02193 BOOST_UBLAS_INLINE
02194 iterator1 begin1 () {
02195 return find1 (0, 0, 0);
02196 }
02197 BOOST_UBLAS_INLINE
02198 iterator1 end1 () {
02199 return find1 (0, size1_, 0);
02200 }
02201
02202 class const_iterator2:
02203 public container_const_reference<mapped_vector_of_mapped_vector>,
02204 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
02205 const_iterator2, value_type> {
02206 public:
02207 typedef typename mapped_vector_of_mapped_vector::value_type value_type;
02208 typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
02209 typedef typename mapped_vector_of_mapped_vector::const_reference reference;
02210 typedef const typename mapped_vector_of_mapped_vector::pointer pointer;
02211
02212 typedef const_iterator1 dual_iterator_type;
02213 typedef const_reverse_iterator1 dual_reverse_iterator_type;
02214
02215
02216 BOOST_UBLAS_INLINE
02217 const_iterator2 ():
02218 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
02219 BOOST_UBLAS_INLINE
02220 const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it):
02221 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
02222 BOOST_UBLAS_INLINE
02223 const_iterator2 (const iterator2 &it):
02224 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
02225
02226
02227 BOOST_UBLAS_INLINE
02228 const_iterator2 &operator ++ () {
02229 if (rank_ == 1 && layout_type::fast_j ())
02230 ++ it_;
02231 else {
02232 const self_type &m = (*this) ();
02233 if (rank_ == 0) {
02234 ++ itv_;
02235 j_ = itv_->first;
02236 } else {
02237 j_ = index2 () + 1;
02238 }
02239 if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
02240 *this = m.find2 (rank_, i_, j_, 1);
02241 else if (rank_ == 1) {
02242 it_ = (*itv_).second.begin ();
02243 if (it_ == (*itv_).second.end () || index1 () != i_)
02244 *this = m.find2 (rank_, i_, j_, 1);
02245 }
02246 }
02247 return *this;
02248 }
02249 BOOST_UBLAS_INLINE
02250 const_iterator2 &operator -- () {
02251 if (rank_ == 1 && layout_type::fast_j ())
02252 -- it_;
02253 else {
02254 const self_type &m = (*this) ();
02255 if (rank_ == 0) {
02256 -- itv_;
02257 j_ = itv_->first;
02258 } else {
02259 j_ = index2 () - 1;
02260 }
02261
02262 if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
02263 *this = m.find2 (rank_, i_, j_, -1);
02264 else if (rank_ == 1) {
02265 it_ = (*itv_).second.begin ();
02266 if (it_ == (*itv_).second.end () || index1 () != i_)
02267 *this = m.find2 (rank_, i_, j_, -1);
02268 }
02269 }
02270 return *this;
02271 }
02272
02273
02274 BOOST_UBLAS_INLINE
02275 const_reference operator * () const {
02276 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
02277 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
02278 if (rank_ == 1) {
02279 return (*it_).second;
02280 } else {
02281 return (*this) () (i_, j_);
02282 }
02283 }
02284
02285 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
02286 BOOST_UBLAS_INLINE
02287 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02288 typename self_type::
02289 #endif
02290 const_iterator1 begin () const {
02291 const self_type &m = (*this) ();
02292 return m.find1 (1, 0, index2 ());
02293 }
02294 BOOST_UBLAS_INLINE
02295 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02296 typename self_type::
02297 #endif
02298 const_iterator1 end () const {
02299 const self_type &m = (*this) ();
02300 return m.find1 (1, m.size1 (), index2 ());
02301 }
02302 BOOST_UBLAS_INLINE
02303 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02304 typename self_type::
02305 #endif
02306 const_reverse_iterator1 rbegin () const {
02307 return const_reverse_iterator1 (end ());
02308 }
02309 BOOST_UBLAS_INLINE
02310 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02311 typename self_type::
02312 #endif
02313 const_reverse_iterator1 rend () const {
02314 return const_reverse_iterator1 (begin ());
02315 }
02316 #endif
02317
02318
02319 BOOST_UBLAS_INLINE
02320 size_type index1 () const {
02321 if (rank_ == 1) {
02322 BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
02323 return layout_type::index_M ((*itv_).first, (*it_).first);
02324 } else {
02325 return i_;
02326 }
02327 }
02328 BOOST_UBLAS_INLINE
02329 size_type index2 () const {
02330 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
02331 if (rank_ == 1) {
02332 BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
02333 return layout_type::index_m ((*itv_).first, (*it_).first);
02334 } else {
02335 return j_;
02336 }
02337 }
02338
02339
02340 BOOST_UBLAS_INLINE
02341 const_iterator2 &operator = (const const_iterator2 &it) {
02342 container_const_reference<self_type>::assign (&it ());
02343 rank_ = it.rank_;
02344 i_ = it.i_;
02345 j_ = it.j_;
02346 itv_ = it.itv_;
02347 it_ = it.it_;
02348 return *this;
02349 }
02350
02351
02352 BOOST_UBLAS_INLINE
02353 bool operator == (const const_iterator2 &it) const {
02354 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
02355
02356 if (rank_ == 1 || it.rank_ == 1) {
02357 return it_ == it.it_;
02358 } else {
02359 return i_ == it.i_ && j_ == it.j_;
02360 }
02361 }
02362
02363 private:
02364 int rank_;
02365 size_type i_;
02366 size_type j_;
02367 vector_const_subiterator_type itv_;
02368 const_subiterator_type it_;
02369 };
02370
02371 BOOST_UBLAS_INLINE
02372 const_iterator2 begin2 () const {
02373 return find2 (0, 0, 0);
02374 }
02375 BOOST_UBLAS_INLINE
02376 const_iterator2 end2 () const {
02377 return find2 (0, 0, size2_);
02378 }
02379
02380 class iterator2:
02381 public container_reference<mapped_vector_of_mapped_vector>,
02382 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
02383 iterator2, value_type> {
02384 public:
02385 typedef typename mapped_vector_of_mapped_vector::value_type value_type;
02386 typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
02387 typedef typename mapped_vector_of_mapped_vector::true_reference reference;
02388 typedef typename mapped_vector_of_mapped_vector::pointer pointer;
02389
02390 typedef iterator1 dual_iterator_type;
02391 typedef reverse_iterator1 dual_reverse_iterator_type;
02392
02393
02394 BOOST_UBLAS_INLINE
02395 iterator2 ():
02396 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
02397 BOOST_UBLAS_INLINE
02398 iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
02399 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
02400
02401
02402 BOOST_UBLAS_INLINE
02403 iterator2 &operator ++ () {
02404 if (rank_ == 1 && layout_type::fast_j ())
02405 ++ it_;
02406 else {
02407 self_type &m = (*this) ();
02408 if (rank_ == 0) {
02409 ++ itv_;
02410 j_ = itv_->first;
02411 } else {
02412 j_ = index2 () + 1;
02413 }
02414 if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
02415 *this = m.find2 (rank_, i_, j_, 1);
02416 else if (rank_ == 1) {
02417 it_ = (*itv_).second.begin ();
02418 if (it_ == (*itv_).second.end () || index1 () != i_)
02419 *this = m.find2 (rank_, i_, j_, 1);
02420 }
02421 }
02422 return *this;
02423 }
02424 BOOST_UBLAS_INLINE
02425 iterator2 &operator -- () {
02426 if (rank_ == 1 && layout_type::fast_j ())
02427 -- it_;
02428 else {
02429 self_type &m = (*this) ();
02430 if (rank_ == 0) {
02431 -- itv_;
02432 j_ = itv_->first;
02433 } else {
02434 j_ = index2 () - 1;
02435 }
02436
02437 if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
02438 *this = m.find2 (rank_, i_, j_, -1);
02439 else if (rank_ == 1) {
02440 it_ = (*itv_).second.begin ();
02441 if (it_ == (*itv_).second.end () || index1 () != i_)
02442 *this = m.find2 (rank_, i_, j_, -1);
02443 }
02444 }
02445 return *this;
02446 }
02447
02448
02449 BOOST_UBLAS_INLINE
02450 reference operator * () const {
02451 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
02452 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
02453 if (rank_ == 1) {
02454 return (*it_).second;
02455 } else {
02456 return (*this) ().at_element (i_, j_);
02457 }
02458 }
02459
02460 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
02461 BOOST_UBLAS_INLINE
02462 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02463 typename self_type::
02464 #endif
02465 iterator1 begin () const {
02466 self_type &m = (*this) ();
02467 return m.find1 (1, 0, index2 ());
02468 }
02469 BOOST_UBLAS_INLINE
02470 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02471 typename self_type::
02472 #endif
02473 iterator1 end () const {
02474 self_type &m = (*this) ();
02475 return m.find1 (1, m.size1 (), index2 ());
02476 }
02477 BOOST_UBLAS_INLINE
02478 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02479 typename self_type::
02480 #endif
02481 reverse_iterator1 rbegin () const {
02482 return reverse_iterator1 (end ());
02483 }
02484 BOOST_UBLAS_INLINE
02485 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02486 typename self_type::
02487 #endif
02488 reverse_iterator1 rend () const {
02489 return reverse_iterator1 (begin ());
02490 }
02491 #endif
02492
02493
02494 BOOST_UBLAS_INLINE
02495 size_type index1 () const {
02496 if (rank_ == 1) {
02497 BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
02498 return layout_type::index_M ((*itv_).first, (*it_).first);
02499 } else {
02500 return i_;
02501 }
02502 }
02503 BOOST_UBLAS_INLINE
02504 size_type index2 () const {
02505 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
02506 if (rank_ == 1) {
02507 BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
02508 return layout_type::index_m ((*itv_).first, (*it_).first);
02509 } else {
02510 return j_;
02511 }
02512 }
02513
02514
02515 BOOST_UBLAS_INLINE
02516 iterator2 &operator = (const iterator2 &it) {
02517 container_reference<self_type>::assign (&it ());
02518 rank_ = it.rank_;
02519 i_ = it.i_;
02520 j_ = it.j_;
02521 itv_ = it.itv_;
02522 it_ = it.it_;
02523 return *this;
02524 }
02525
02526
02527 BOOST_UBLAS_INLINE
02528 bool operator == (const iterator2 &it) const {
02529 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
02530
02531 if (rank_ == 1 || it.rank_ == 1) {
02532 return it_ == it.it_;
02533 } else {
02534 return i_ == it.i_ && j_ == it.j_;
02535 }
02536 }
02537
02538 private:
02539 int rank_;
02540 size_type i_;
02541 size_type j_;
02542 vector_subiterator_type itv_;
02543 subiterator_type it_;
02544
02545 friend class const_iterator2;
02546 };
02547
02548 BOOST_UBLAS_INLINE
02549 iterator2 begin2 () {
02550 return find2 (0, 0, 0);
02551 }
02552 BOOST_UBLAS_INLINE
02553 iterator2 end2 () {
02554 return find2 (0, 0, size2_);
02555 }
02556
02557
02558
02559 BOOST_UBLAS_INLINE
02560 const_reverse_iterator1 rbegin1 () const {
02561 return const_reverse_iterator1 (end1 ());
02562 }
02563 BOOST_UBLAS_INLINE
02564 const_reverse_iterator1 rend1 () const {
02565 return const_reverse_iterator1 (begin1 ());
02566 }
02567
02568 BOOST_UBLAS_INLINE
02569 reverse_iterator1 rbegin1 () {
02570 return reverse_iterator1 (end1 ());
02571 }
02572 BOOST_UBLAS_INLINE
02573 reverse_iterator1 rend1 () {
02574 return reverse_iterator1 (begin1 ());
02575 }
02576
02577 BOOST_UBLAS_INLINE
02578 const_reverse_iterator2 rbegin2 () const {
02579 return const_reverse_iterator2 (end2 ());
02580 }
02581 BOOST_UBLAS_INLINE
02582 const_reverse_iterator2 rend2 () const {
02583 return const_reverse_iterator2 (begin2 ());
02584 }
02585
02586 BOOST_UBLAS_INLINE
02587 reverse_iterator2 rbegin2 () {
02588 return reverse_iterator2 (end2 ());
02589 }
02590 BOOST_UBLAS_INLINE
02591 reverse_iterator2 rend2 () {
02592 return reverse_iterator2 (begin2 ());
02593 }
02594
02595
02596 template<class Archive>
02597 void serialize(Archive & ar, const unsigned int ){
02598 serialization::collection_size_type s1 (size1_);
02599 serialization::collection_size_type s2 (size2_);
02600 ar & serialization::make_nvp("size1",s1);
02601 ar & serialization::make_nvp("size2",s2);
02602 if (Archive::is_loading::value) {
02603 size1_ = s1;
02604 size2_ = s2;
02605 }
02606 ar & serialization::make_nvp("data", data_);
02607 }
02608
02609 private:
02610 size_type size1_;
02611 size_type size2_;
02612 array_type data_;
02613 static const value_type zero_;
02614 };
02615
02616 template<class T, class L, class A>
02617 const typename mapped_vector_of_mapped_vector<T, L, A>::value_type mapped_vector_of_mapped_vector<T, L, A>::zero_ = value_type();
02618
02619
02620
02621
02622 template<class T, class L, std::size_t IB, class IA, class TA>
02623 class compressed_matrix:
02624 public matrix_container<compressed_matrix<T, L, IB, IA, TA> > {
02625
02626 typedef T &true_reference;
02627 typedef T *pointer;
02628 typedef const T *const_pointer;
02629 typedef L layout_type;
02630 typedef compressed_matrix<T, L, IB, IA, TA> self_type;
02631 public:
02632 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
02633 using matrix_container<self_type>::operator ();
02634 #endif
02635
02636
02637 typedef typename IA::value_type size_type;
02638
02639 typedef typename IA::size_type array_size_type;
02640
02641 typedef typename IA::difference_type difference_type;
02642 typedef T value_type;
02643 typedef const T &const_reference;
02644 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
02645 typedef T &reference;
02646 #else
02647 typedef sparse_matrix_element<self_type> reference;
02648 #endif
02649 typedef IA index_array_type;
02650 typedef TA value_array_type;
02651 typedef const matrix_reference<const self_type> const_closure_type;
02652 typedef matrix_reference<self_type> closure_type;
02653 typedef compressed_vector<T, IB, IA, TA> vector_temporary_type;
02654 typedef self_type matrix_temporary_type;
02655 typedef sparse_tag storage_category;
02656 typedef typename L::orientation_category orientation_category;
02657
02658
02659 BOOST_UBLAS_INLINE
02660 compressed_matrix ():
02661 matrix_container<self_type> (),
02662 size1_ (0), size2_ (0), capacity_ (restrict_capacity (0)),
02663 filled1_ (1), filled2_ (0),
02664 index1_data_ (layout_type::size_M (size1_, size2_) + 1), index2_data_ (capacity_), value_data_ (capacity_) {
02665 index1_data_ [filled1_ - 1] = k_based (filled2_);
02666 storage_invariants ();
02667 }
02668 BOOST_UBLAS_INLINE
02669 compressed_matrix (size_type size1, size_type size2, size_type non_zeros = 0):
02670 matrix_container<self_type> (),
02671 size1_ (size1), size2_ (size2), capacity_ (restrict_capacity (non_zeros)),
02672 filled1_ (1), filled2_ (0),
02673 index1_data_ (layout_type::size_M (size1_, size2_) + 1), index2_data_ (capacity_), value_data_ (capacity_) {
02674 index1_data_ [filled1_ - 1] = k_based (filled2_);
02675 storage_invariants ();
02676 }
02677 BOOST_UBLAS_INLINE
02678 compressed_matrix (const compressed_matrix &m):
02679 matrix_container<self_type> (),
02680 size1_ (m.size1_), size2_ (m.size2_), capacity_ (m.capacity_),
02681 filled1_ (m.filled1_), filled2_ (m.filled2_),
02682 index1_data_ (m.index1_data_), index2_data_ (m.index2_data_), value_data_ (m.value_data_) {
02683 storage_invariants ();
02684 }
02685
02686 BOOST_UBLAS_INLINE
02687 compressed_matrix (const coordinate_matrix<T, L, IB, IA, TA> &m):
02688 matrix_container<self_type> (),
02689 size1_ (m.size1()), size2_ (m.size2()),
02690 index1_data_ (layout_type::size_M (size1_, size2_) + 1)
02691 {
02692 m.sort();
02693 reserve(m.nnz(), false);
02694 filled2_ = m.nnz();
02695 const_subiterator_type i_start = m.index1_data().begin();
02696 const_subiterator_type i_end = (i_start + filled2_);
02697 const_subiterator_type i = i_start;
02698 size_type r = 1;
02699 for (; (r < layout_type::size_M (size1_, size2_)) && (i != i_end); ++r) {
02700 i = std::lower_bound(i, i_end, r);
02701 index1_data_[r] = k_based( i - i_start );
02702 }
02703 filled1_ = r + 1;
02704 std::copy( m.index2_data().begin(), m.index2_data().begin() + filled2_, index2_data_.begin());
02705 std::copy( m.value_data().begin(), m.value_data().begin() + filled2_, value_data_.begin());
02706 index1_data_ [filled1_ - 1] = k_based(filled2_);
02707 storage_invariants ();
02708 }
02709
02710 template<class AE>
02711 BOOST_UBLAS_INLINE
02712 compressed_matrix (const matrix_expression<AE> &ae, size_type non_zeros = 0):
02713 matrix_container<self_type> (),
02714 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), capacity_ (restrict_capacity (non_zeros)),
02715 filled1_ (1), filled2_ (0),
02716 index1_data_ (layout_type::size_M (ae ().size1 (), ae ().size2 ()) + 1),
02717 index2_data_ (capacity_), value_data_ (capacity_) {
02718 index1_data_ [filled1_ - 1] = k_based (filled2_);
02719 storage_invariants ();
02720 matrix_assign<scalar_assign> (*this, ae);
02721 }
02722
02723
02724 BOOST_UBLAS_INLINE
02725 size_type size1 () const {
02726 return size1_;
02727 }
02728 BOOST_UBLAS_INLINE
02729 size_type size2 () const {
02730 return size2_;
02731 }
02732 BOOST_UBLAS_INLINE
02733 size_type nnz_capacity () const {
02734 return capacity_;
02735 }
02736 BOOST_UBLAS_INLINE
02737 size_type nnz () const {
02738 return filled2_;
02739 }
02740
02741
02742 BOOST_UBLAS_INLINE
02743 static size_type index_base () {
02744 return IB;
02745 }
02746 BOOST_UBLAS_INLINE
02747 array_size_type filled1 () const {
02748 return filled1_;
02749 }
02750 BOOST_UBLAS_INLINE
02751 array_size_type filled2 () const {
02752 return filled2_;
02753 }
02754 BOOST_UBLAS_INLINE
02755 const index_array_type &index1_data () const {
02756 return index1_data_;
02757 }
02758 BOOST_UBLAS_INLINE
02759 const index_array_type &index2_data () const {
02760 return index2_data_;
02761 }
02762 BOOST_UBLAS_INLINE
02763 const value_array_type &value_data () const {
02764 return value_data_;
02765 }
02766 BOOST_UBLAS_INLINE
02767 void set_filled (const array_size_type& filled1, const array_size_type& filled2) {
02768 filled1_ = filled1;
02769 filled2_ = filled2;
02770 storage_invariants ();
02771 }
02772 BOOST_UBLAS_INLINE
02773 index_array_type &index1_data () {
02774 return index1_data_;
02775 }
02776 BOOST_UBLAS_INLINE
02777 index_array_type &index2_data () {
02778 return index2_data_;
02779 }
02780 BOOST_UBLAS_INLINE
02781 value_array_type &value_data () {
02782 return value_data_;
02783 }
02784 BOOST_UBLAS_INLINE
02785 void complete_index1_data () {
02786 while (filled1_ <= layout_type::size_M (size1_, size2_)) {
02787 this->index1_data_ [filled1_] = k_based (filled2_);
02788 ++ this->filled1_;
02789 }
02790 }
02791
02792
02793 private:
02794 BOOST_UBLAS_INLINE
02795 size_type restrict_capacity (size_type non_zeros) const {
02796 non_zeros = (std::max) (non_zeros, (std::min) (size1_, size2_));
02797
02798
02799 if (size1_ > 0 && non_zeros / size1_ >= size2_)
02800 non_zeros = size1_ * size2_;
02801 return non_zeros;
02802 }
02803 public:
02804 BOOST_UBLAS_INLINE
02805 void resize (size_type size1, size_type size2, bool preserve = true) {
02806
02807 BOOST_UBLAS_CHECK (!preserve, internal_logic ());
02808 size1_ = size1;
02809 size2_ = size2;
02810 capacity_ = restrict_capacity (capacity_);
02811 filled1_ = 1;
02812 filled2_ = 0;
02813 index1_data_.resize (layout_type::size_M (size1_, size2_) + 1);
02814 index2_data_.resize (capacity_);
02815 value_data_.resize (capacity_);
02816 index1_data_ [filled1_ - 1] = k_based (filled2_);
02817 storage_invariants ();
02818 }
02819
02820
02821 BOOST_UBLAS_INLINE
02822 void reserve (size_type non_zeros, bool preserve = true) {
02823 capacity_ = restrict_capacity (non_zeros);
02824 if (preserve) {
02825 index2_data_.resize (capacity_, size_type ());
02826 value_data_.resize (capacity_, value_type ());
02827 filled2_ = (std::min) (capacity_, filled2_);
02828 }
02829 else {
02830 index2_data_.resize (capacity_);
02831 value_data_.resize (capacity_);
02832 filled1_ = 1;
02833 filled2_ = 0;
02834 index1_data_ [filled1_ - 1] = k_based (filled2_);
02835 }
02836 storage_invariants ();
02837 }
02838
02839
02840 BOOST_UBLAS_INLINE
02841 pointer find_element (size_type i, size_type j) {
02842 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
02843 }
02844 BOOST_UBLAS_INLINE
02845 const_pointer find_element (size_type i, size_type j) const {
02846 size_type element1 (layout_type::index_M (i, j));
02847 size_type element2 (layout_type::index_m (i, j));
02848 if (filled1_ <= element1 + 1)
02849 return 0;
02850 vector_const_subiterator_type itv (index1_data_.begin () + element1);
02851 const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
02852 const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
02853 const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
02854 if (it == it_end || *it != k_based (element2))
02855 return 0;
02856 return &value_data_ [it - index2_data_.begin ()];
02857 }
02858
02859
02860 BOOST_UBLAS_INLINE
02861 const_reference operator () (size_type i, size_type j) const {
02862 const_pointer p = find_element (i, j);
02863 if (p)
02864 return *p;
02865 else
02866 return zero_;
02867 }
02868 BOOST_UBLAS_INLINE
02869 reference operator () (size_type i, size_type j) {
02870 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
02871 size_type element1 (layout_type::index_M (i, j));
02872 size_type element2 (layout_type::index_m (i, j));
02873 if (filled1_ <= element1 + 1)
02874 return insert_element (i, j, value_type());
02875 pointer p = find_element (i, j);
02876 if (p)
02877 return *p;
02878 else
02879 return insert_element (i, j, value_type());
02880 #else
02881 return reference (*this, i, j);
02882 #endif
02883 }
02884
02885
02886 BOOST_UBLAS_INLINE
02887 true_reference insert_element (size_type i, size_type j, const_reference t) {
02888 BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ());
02889 if (filled2_ >= capacity_)
02890 reserve (2 * filled2_, true);
02891 BOOST_UBLAS_CHECK (filled2_ < capacity_, internal_logic ());
02892 size_type element1 = layout_type::index_M (i, j);
02893 size_type element2 = layout_type::index_m (i, j);
02894 while (filled1_ <= element1 + 1) {
02895 index1_data_ [filled1_] = k_based (filled2_);
02896 ++ filled1_;
02897 }
02898 vector_subiterator_type itv (index1_data_.begin () + element1);
02899 subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
02900 subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
02901 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
02902 typename std::iterator_traits<subiterator_type>::difference_type n = it - index2_data_.begin ();
02903 BOOST_UBLAS_CHECK (it == it_end || *it != k_based (element2), internal_logic ());
02904 ++ filled2_;
02905 it = index2_data_.begin () + n;
02906 std::copy_backward (it, index2_data_.begin () + filled2_ - 1, index2_data_.begin () + filled2_);
02907 *it = k_based (element2);
02908 typename value_array_type::iterator itt (value_data_.begin () + n);
02909 std::copy_backward (itt, value_data_.begin () + filled2_ - 1, value_data_.begin () + filled2_);
02910 *itt = t;
02911 while (element1 + 1 < filled1_) {
02912 ++ index1_data_ [element1 + 1];
02913 ++ element1;
02914 }
02915 storage_invariants ();
02916 return *itt;
02917 }
02918 BOOST_UBLAS_INLINE
02919 void erase_element (size_type i, size_type j) {
02920 size_type element1 = layout_type::index_M (i, j);
02921 size_type element2 = layout_type::index_m (i, j);
02922 if (element1 + 1 >= filled1_)
02923 return;
02924 vector_subiterator_type itv (index1_data_.begin () + element1);
02925 subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
02926 subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
02927 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
02928 if (it != it_end && *it == k_based (element2)) {
02929 typename std::iterator_traits<subiterator_type>::difference_type n = it - index2_data_.begin ();
02930 std::copy (it + 1, index2_data_.begin () + filled2_, it);
02931 typename value_array_type::iterator itt (value_data_.begin () + n);
02932 std::copy (itt + 1, value_data_.begin () + filled2_, itt);
02933 -- filled2_;
02934 while (index1_data_ [filled1_ - 2] > k_based (filled2_)) {
02935 index1_data_ [filled1_ - 1] = 0;
02936 -- filled1_;
02937 }
02938 while (element1 + 1 < filled1_) {
02939 -- index1_data_ [element1 + 1];
02940 ++ element1;
02941 }
02942 }
02943 storage_invariants ();
02944 }
02945
02946
02947 BOOST_UBLAS_INLINE
02948 void clear () {
02949 filled1_ = 1;
02950 filled2_ = 0;
02951 index1_data_ [filled1_ - 1] = k_based (filled2_);
02952 storage_invariants ();
02953 }
02954
02955
02956 BOOST_UBLAS_INLINE
02957 compressed_matrix &operator = (const compressed_matrix &m) {
02958 if (this != &m) {
02959 size1_ = m.size1_;
02960 size2_ = m.size2_;
02961 capacity_ = m.capacity_;
02962 filled1_ = m.filled1_;
02963 filled2_ = m.filled2_;
02964 index1_data_ = m.index1_data_;
02965 index2_data_ = m.index2_data_;
02966 value_data_ = m.value_data_;
02967 }
02968 storage_invariants ();
02969 return *this;
02970 }
02971 template<class C>
02972 BOOST_UBLAS_INLINE
02973 compressed_matrix &operator = (const matrix_container<C> &m) {
02974 resize (m ().size1 (), m ().size2 (), false);
02975 assign (m);
02976 return *this;
02977 }
02978 BOOST_UBLAS_INLINE
02979 compressed_matrix &assign_temporary (compressed_matrix &m) {
02980 swap (m);
02981 return *this;
02982 }
02983 template<class AE>
02984 BOOST_UBLAS_INLINE
02985 compressed_matrix &operator = (const matrix_expression<AE> &ae) {
02986 self_type temporary (ae, capacity_);
02987 return assign_temporary (temporary);
02988 }
02989 template<class AE>
02990 BOOST_UBLAS_INLINE
02991 compressed_matrix &assign (const matrix_expression<AE> &ae) {
02992 matrix_assign<scalar_assign> (*this, ae);
02993 return *this;
02994 }
02995 template<class AE>
02996 BOOST_UBLAS_INLINE
02997 compressed_matrix& operator += (const matrix_expression<AE> &ae) {
02998 self_type temporary (*this + ae, capacity_);
02999 return assign_temporary (temporary);
03000 }
03001 template<class C>
03002 BOOST_UBLAS_INLINE
03003 compressed_matrix &operator += (const matrix_container<C> &m) {
03004 plus_assign (m);
03005 return *this;
03006 }
03007 template<class AE>
03008 BOOST_UBLAS_INLINE
03009 compressed_matrix &plus_assign (const matrix_expression<AE> &ae) {
03010 matrix_assign<scalar_plus_assign> (*this, ae);
03011 return *this;
03012 }
03013 template<class AE>
03014 BOOST_UBLAS_INLINE
03015 compressed_matrix& operator -= (const matrix_expression<AE> &ae) {
03016 self_type temporary (*this - ae, capacity_);
03017 return assign_temporary (temporary);
03018 }
03019 template<class C>
03020 BOOST_UBLAS_INLINE
03021 compressed_matrix &operator -= (const matrix_container<C> &m) {
03022 minus_assign (m);
03023 return *this;
03024 }
03025 template<class AE>
03026 BOOST_UBLAS_INLINE
03027 compressed_matrix &minus_assign (const matrix_expression<AE> &ae) {
03028 matrix_assign<scalar_minus_assign> (*this, ae);
03029 return *this;
03030 }
03031 template<class AT>
03032 BOOST_UBLAS_INLINE
03033 compressed_matrix& operator *= (const AT &at) {
03034 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
03035 return *this;
03036 }
03037 template<class AT>
03038 BOOST_UBLAS_INLINE
03039 compressed_matrix& operator /= (const AT &at) {
03040 matrix_assign_scalar<scalar_divides_assign> (*this, at);
03041 return *this;
03042 }
03043
03044
03045 BOOST_UBLAS_INLINE
03046 void swap (compressed_matrix &m) {
03047 if (this != &m) {
03048 std::swap (size1_, m.size1_);
03049 std::swap (size2_, m.size2_);
03050 std::swap (capacity_, m.capacity_);
03051 std::swap (filled1_, m.filled1_);
03052 std::swap (filled2_, m.filled2_);
03053 index1_data_.swap (m.index1_data_);
03054 index2_data_.swap (m.index2_data_);
03055 value_data_.swap (m.value_data_);
03056 }
03057 storage_invariants ();
03058 }
03059 BOOST_UBLAS_INLINE
03060 friend void swap (compressed_matrix &m1, compressed_matrix &m2) {
03061 m1.swap (m2);
03062 }
03063
03064
03065 BOOST_UBLAS_INLINE
03066 void push_back (size_type i, size_type j, const_reference t) {
03067 if (filled2_ >= capacity_)
03068 reserve (2 * filled2_, true);
03069 BOOST_UBLAS_CHECK (filled2_ < capacity_, internal_logic ());
03070 size_type element1 = layout_type::index_M (i, j);
03071 size_type element2 = layout_type::index_m (i, j);
03072 while (filled1_ < element1 + 2) {
03073 index1_data_ [filled1_] = k_based (filled2_);
03074 ++ filled1_;
03075 }
03076
03077 BOOST_UBLAS_CHECK ((filled1_ == element1 + 2 &&
03078 (filled2_ == zero_based (index1_data_ [filled1_ - 2]) ||
03079 index2_data_ [filled2_ - 1] < k_based (element2))), external_logic ());
03080 ++ filled2_;
03081 index1_data_ [filled1_ - 1] = k_based (filled2_);
03082 index2_data_ [filled2_ - 1] = k_based (element2);
03083 value_data_ [filled2_ - 1] = t;
03084 storage_invariants ();
03085 }
03086 BOOST_UBLAS_INLINE
03087 void pop_back () {
03088 BOOST_UBLAS_CHECK (filled1_ > 0 && filled2_ > 0, external_logic ());
03089 -- filled2_;
03090 while (index1_data_ [filled1_ - 2] > k_based (filled2_)) {
03091 index1_data_ [filled1_ - 1] = 0;
03092 -- filled1_;
03093 }
03094 -- index1_data_ [filled1_ - 1];
03095 storage_invariants ();
03096 }
03097
03098
03099 private:
03100
03101 typedef typename IA::const_iterator vector_const_subiterator_type;
03102 typedef typename IA::iterator vector_subiterator_type;
03103 typedef typename IA::const_iterator const_subiterator_type;
03104 typedef typename IA::iterator subiterator_type;
03105
03106 BOOST_UBLAS_INLINE
03107 true_reference at_element (size_type i, size_type j) {
03108 pointer p = find_element (i, j);
03109 BOOST_UBLAS_CHECK (p, bad_index ());
03110 return *p;
03111 }
03112
03113 public:
03114 class const_iterator1;
03115 class iterator1;
03116 class const_iterator2;
03117 class iterator2;
03118 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
03119 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
03120 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
03121 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
03122
03123
03124
03125 const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
03126 for (;;) {
03127 array_size_type address1 (layout_type::index_M (i, j));
03128 array_size_type address2 (layout_type::index_m (i, j));
03129 vector_const_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
03130 if (filled1_ <= address1 + 1)
03131 return const_iterator1 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
03132
03133 const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
03134 const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
03135
03136 const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
03137 if (rank == 0)
03138 return const_iterator1 (*this, rank, i, j, itv, it);
03139 if (it != it_end && zero_based (*it) == address2)
03140 return const_iterator1 (*this, rank, i, j, itv, it);
03141 if (direction > 0) {
03142 if (layout_type::fast_i ()) {
03143 if (it == it_end)
03144 return const_iterator1 (*this, rank, i, j, itv, it);
03145 i = zero_based (*it);
03146 } else {
03147 if (i >= size1_)
03148 return const_iterator1 (*this, rank, i, j, itv, it);
03149 ++ i;
03150 }
03151 } else {
03152 if (layout_type::fast_i ()) {
03153 if (it == index2_data_.begin () + zero_based (*itv))
03154 return const_iterator1 (*this, rank, i, j, itv, it);
03155 i = zero_based (*(it - 1));
03156 } else {
03157 if (i == 0)
03158 return const_iterator1 (*this, rank, i, j, itv, it);
03159 -- i;
03160 }
03161 }
03162 }
03163 }
03164
03165 iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
03166 for (;;) {
03167 array_size_type address1 (layout_type::index_M (i, j));
03168 array_size_type address2 (layout_type::index_m (i, j));
03169 vector_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
03170 if (filled1_ <= address1 + 1)
03171 return iterator1 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
03172
03173 subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
03174 subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
03175
03176 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
03177 if (rank == 0)
03178 return iterator1 (*this, rank, i, j, itv, it);
03179 if (it != it_end && zero_based (*it) == address2)
03180 return iterator1 (*this, rank, i, j, itv, it);
03181 if (direction > 0) {
03182 if (layout_type::fast_i ()) {
03183 if (it == it_end)
03184 return iterator1 (*this, rank, i, j, itv, it);
03185 i = zero_based (*it);
03186 } else {
03187 if (i >= size1_)
03188 return iterator1 (*this, rank, i, j, itv, it);
03189 ++ i;
03190 }
03191 } else {
03192 if (layout_type::fast_i ()) {
03193 if (it == index2_data_.begin () + zero_based (*itv))
03194 return iterator1 (*this, rank, i, j, itv, it);
03195 i = zero_based (*(it - 1));
03196 } else {
03197 if (i == 0)
03198 return iterator1 (*this, rank, i, j, itv, it);
03199 -- i;
03200 }
03201 }
03202 }
03203 }
03204
03205 const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
03206 for (;;) {
03207 array_size_type address1 (layout_type::index_M (i, j));
03208 array_size_type address2 (layout_type::index_m (i, j));
03209 vector_const_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
03210 if (filled1_ <= address1 + 1)
03211 return const_iterator2 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
03212
03213 const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
03214 const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
03215
03216 const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
03217 if (rank == 0)
03218 return const_iterator2 (*this, rank, i, j, itv, it);
03219 if (it != it_end && zero_based (*it) == address2)
03220 return const_iterator2 (*this, rank, i, j, itv, it);
03221 if (direction > 0) {
03222 if (layout_type::fast_j ()) {
03223 if (it == it_end)
03224 return const_iterator2 (*this, rank, i, j, itv, it);
03225 j = zero_based (*it);
03226 } else {
03227 if (j >= size2_)
03228 return const_iterator2 (*this, rank, i, j, itv, it);
03229 ++ j;
03230 }
03231 } else {
03232 if (layout_type::fast_j ()) {
03233 if (it == index2_data_.begin () + zero_based (*itv))
03234 return const_iterator2 (*this, rank, i, j, itv, it);
03235 j = zero_based (*(it - 1));
03236 } else {
03237 if (j == 0)
03238 return const_iterator2 (*this, rank, i, j, itv, it);
03239 -- j;
03240 }
03241 }
03242 }
03243 }
03244
03245 iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
03246 for (;;) {
03247 array_size_type address1 (layout_type::index_M (i, j));
03248 array_size_type address2 (layout_type::index_m (i, j));
03249 vector_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
03250 if (filled1_ <= address1 + 1)
03251 return iterator2 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
03252
03253 subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
03254 subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
03255
03256 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
03257 if (rank == 0)
03258 return iterator2 (*this, rank, i, j, itv, it);
03259 if (it != it_end && zero_based (*it) == address2)
03260 return iterator2 (*this, rank, i, j, itv, it);
03261 if (direction > 0) {
03262 if (layout_type::fast_j ()) {
03263 if (it == it_end)
03264 return iterator2 (*this, rank, i, j, itv, it);
03265 j = zero_based (*it);
03266 } else {
03267 if (j >= size2_)
03268 return iterator2 (*this, rank, i, j, itv, it);
03269 ++ j;
03270 }
03271 } else {
03272 if (layout_type::fast_j ()) {
03273 if (it == index2_data_.begin () + zero_based (*itv))
03274 return iterator2 (*this, rank, i, j, itv, it);
03275 j = zero_based (*(it - 1));
03276 } else {
03277 if (j == 0)
03278 return iterator2 (*this, rank, i, j, itv, it);
03279 -- j;
03280 }
03281 }
03282 }
03283 }
03284
03285
03286 class const_iterator1:
03287 public container_const_reference<compressed_matrix>,
03288 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
03289 const_iterator1, value_type> {
03290 public:
03291 typedef typename compressed_matrix::value_type value_type;
03292 typedef typename compressed_matrix::difference_type difference_type;
03293 typedef typename compressed_matrix::const_reference reference;
03294 typedef const typename compressed_matrix::pointer pointer;
03295
03296 typedef const_iterator2 dual_iterator_type;
03297 typedef const_reverse_iterator2 dual_reverse_iterator_type;
03298
03299
03300 BOOST_UBLAS_INLINE
03301 const_iterator1 ():
03302 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
03303 BOOST_UBLAS_INLINE
03304 const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it):
03305 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
03306 BOOST_UBLAS_INLINE
03307 const_iterator1 (const iterator1 &it):
03308 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
03309
03310
03311 BOOST_UBLAS_INLINE
03312 const_iterator1 &operator ++ () {
03313 if (rank_ == 1 && layout_type::fast_i ())
03314 ++ it_;
03315 else {
03316 i_ = index1 () + 1;
03317 if (rank_ == 1)
03318 *this = (*this) ().find1 (rank_, i_, j_, 1);
03319 }
03320 return *this;
03321 }
03322 BOOST_UBLAS_INLINE
03323 const_iterator1 &operator -- () {
03324 if (rank_ == 1 && layout_type::fast_i ())
03325 -- it_;
03326 else {
03327 --i_;
03328 if (rank_ == 1)
03329 *this = (*this) ().find1 (rank_, i_, j_, -1);
03330 }
03331 return *this;
03332 }
03333
03334
03335 BOOST_UBLAS_INLINE
03336 const_reference operator * () const {
03337 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
03338 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
03339 if (rank_ == 1) {
03340 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
03341 } else {
03342 return (*this) () (i_, j_);
03343 }
03344 }
03345
03346 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
03347 BOOST_UBLAS_INLINE
03348 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03349 typename self_type::
03350 #endif
03351 const_iterator2 begin () const {
03352 const self_type &m = (*this) ();
03353 return m.find2 (1, index1 (), 0);
03354 }
03355 BOOST_UBLAS_INLINE
03356 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03357 typename self_type::
03358 #endif
03359 const_iterator2 end () const {
03360 const self_type &m = (*this) ();
03361 return m.find2 (1, index1 (), m.size2 ());
03362 }
03363 BOOST_UBLAS_INLINE
03364 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03365 typename self_type::
03366 #endif
03367 const_reverse_iterator2 rbegin () const {
03368 return const_reverse_iterator2 (end ());
03369 }
03370 BOOST_UBLAS_INLINE
03371 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03372 typename self_type::
03373 #endif
03374 const_reverse_iterator2 rend () const {
03375 return const_reverse_iterator2 (begin ());
03376 }
03377 #endif
03378
03379
03380 BOOST_UBLAS_INLINE
03381 size_type index1 () const {
03382 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
03383 if (rank_ == 1) {
03384 BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
03385 return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
03386 } else {
03387 return i_;
03388 }
03389 }
03390 BOOST_UBLAS_INLINE
03391 size_type index2 () const {
03392 if (rank_ == 1) {
03393 BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
03394 return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
03395 } else {
03396 return j_;
03397 }
03398 }
03399
03400
03401 BOOST_UBLAS_INLINE
03402 const_iterator1 &operator = (const const_iterator1 &it) {
03403 container_const_reference<self_type>::assign (&it ());
03404 rank_ = it.rank_;
03405 i_ = it.i_;
03406 j_ = it.j_;
03407 itv_ = it.itv_;
03408 it_ = it.it_;
03409 return *this;
03410 }
03411
03412
03413 BOOST_UBLAS_INLINE
03414 bool operator == (const const_iterator1 &it) const {
03415 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
03416
03417 if (rank_ == 1 || it.rank_ == 1) {
03418 return it_ == it.it_;
03419 } else {
03420 return i_ == it.i_ && j_ == it.j_;
03421 }
03422 }
03423
03424 private:
03425 int rank_;
03426 size_type i_;
03427 size_type j_;
03428 vector_const_subiterator_type itv_;
03429 const_subiterator_type it_;
03430 };
03431
03432 BOOST_UBLAS_INLINE
03433 const_iterator1 begin1 () const {
03434 return find1 (0, 0, 0);
03435 }
03436 BOOST_UBLAS_INLINE
03437 const_iterator1 end1 () const {
03438 return find1 (0, size1_, 0);
03439 }
03440
03441 class iterator1:
03442 public container_reference<compressed_matrix>,
03443 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
03444 iterator1, value_type> {
03445 public:
03446 typedef typename compressed_matrix::value_type value_type;
03447 typedef typename compressed_matrix::difference_type difference_type;
03448 typedef typename compressed_matrix::true_reference reference;
03449 typedef typename compressed_matrix::pointer pointer;
03450
03451 typedef iterator2 dual_iterator_type;
03452 typedef reverse_iterator2 dual_reverse_iterator_type;
03453
03454
03455 BOOST_UBLAS_INLINE
03456 iterator1 ():
03457 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
03458 BOOST_UBLAS_INLINE
03459 iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
03460 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
03461
03462
03463 BOOST_UBLAS_INLINE
03464 iterator1 &operator ++ () {
03465 if (rank_ == 1 && layout_type::fast_i ())
03466 ++ it_;
03467 else {
03468 i_ = index1 () + 1;
03469 if (rank_ == 1)
03470 *this = (*this) ().find1 (rank_, i_, j_, 1);
03471 }
03472 return *this;
03473 }
03474 BOOST_UBLAS_INLINE
03475 iterator1 &operator -- () {
03476 if (rank_ == 1 && layout_type::fast_i ())
03477 -- it_;
03478 else {
03479 --i_;
03480 if (rank_ == 1)
03481 *this = (*this) ().find1 (rank_, i_, j_, -1);
03482 }
03483 return *this;
03484 }
03485
03486
03487 BOOST_UBLAS_INLINE
03488 reference operator * () const {
03489 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
03490 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
03491 if (rank_ == 1) {
03492 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
03493 } else {
03494 return (*this) ().at_element (i_, j_);
03495 }
03496 }
03497
03498 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
03499 BOOST_UBLAS_INLINE
03500 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03501 typename self_type::
03502 #endif
03503 iterator2 begin () const {
03504 self_type &m = (*this) ();
03505 return m.find2 (1, index1 (), 0);
03506 }
03507 BOOST_UBLAS_INLINE
03508 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03509 typename self_type::
03510 #endif
03511 iterator2 end () const {
03512 self_type &m = (*this) ();
03513 return m.find2 (1, index1 (), m.size2 ());
03514 }
03515 BOOST_UBLAS_INLINE
03516 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03517 typename self_type::
03518 #endif
03519 reverse_iterator2 rbegin () const {
03520 return reverse_iterator2 (end ());
03521 }
03522 BOOST_UBLAS_INLINE
03523 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03524 typename self_type::
03525 #endif
03526 reverse_iterator2 rend () const {
03527 return reverse_iterator2 (begin ());
03528 }
03529 #endif
03530
03531
03532 BOOST_UBLAS_INLINE
03533 size_type index1 () const {
03534 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
03535 if (rank_ == 1) {
03536 BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
03537 return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
03538 } else {
03539 return i_;
03540 }
03541 }
03542 BOOST_UBLAS_INLINE
03543 size_type index2 () const {
03544 if (rank_ == 1) {
03545 BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
03546 return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
03547 } else {
03548 return j_;
03549 }
03550 }
03551
03552
03553 BOOST_UBLAS_INLINE
03554 iterator1 &operator = (const iterator1 &it) {
03555 container_reference<self_type>::assign (&it ());
03556 rank_ = it.rank_;
03557 i_ = it.i_;
03558 j_ = it.j_;
03559 itv_ = it.itv_;
03560 it_ = it.it_;
03561 return *this;
03562 }
03563
03564
03565 BOOST_UBLAS_INLINE
03566 bool operator == (const iterator1 &it) const {
03567 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
03568
03569 if (rank_ == 1 || it.rank_ == 1) {
03570 return it_ == it.it_;
03571 } else {
03572 return i_ == it.i_ && j_ == it.j_;
03573 }
03574 }
03575
03576 private:
03577 int rank_;
03578 size_type i_;
03579 size_type j_;
03580 vector_subiterator_type itv_;
03581 subiterator_type it_;
03582
03583 friend class const_iterator1;
03584 };
03585
03586 BOOST_UBLAS_INLINE
03587 iterator1 begin1 () {
03588 return find1 (0, 0, 0);
03589 }
03590 BOOST_UBLAS_INLINE
03591 iterator1 end1 () {
03592 return find1 (0, size1_, 0);
03593 }
03594
03595 class const_iterator2:
03596 public container_const_reference<compressed_matrix>,
03597 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
03598 const_iterator2, value_type> {
03599 public:
03600 typedef typename compressed_matrix::value_type value_type;
03601 typedef typename compressed_matrix::difference_type difference_type;
03602 typedef typename compressed_matrix::const_reference reference;
03603 typedef const typename compressed_matrix::pointer pointer;
03604
03605 typedef const_iterator1 dual_iterator_type;
03606 typedef const_reverse_iterator1 dual_reverse_iterator_type;
03607
03608
03609 BOOST_UBLAS_INLINE
03610 const_iterator2 ():
03611 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
03612 BOOST_UBLAS_INLINE
03613 const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type itv, const const_subiterator_type &it):
03614 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
03615 BOOST_UBLAS_INLINE
03616 const_iterator2 (const iterator2 &it):
03617 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
03618
03619
03620 BOOST_UBLAS_INLINE
03621 const_iterator2 &operator ++ () {
03622 if (rank_ == 1 && layout_type::fast_j ())
03623 ++ it_;
03624 else {
03625 j_ = index2 () + 1;
03626 if (rank_ == 1)
03627 *this = (*this) ().find2 (rank_, i_, j_, 1);
03628 }
03629 return *this;
03630 }
03631 BOOST_UBLAS_INLINE
03632 const_iterator2 &operator -- () {
03633 if (rank_ == 1 && layout_type::fast_j ())
03634 -- it_;
03635 else {
03636 --j_;
03637 if (rank_ == 1)
03638 *this = (*this) ().find2 (rank_, i_, j_, -1);
03639 }
03640 return *this;
03641 }
03642
03643
03644 BOOST_UBLAS_INLINE
03645 const_reference operator * () const {
03646 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
03647 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
03648 if (rank_ == 1) {
03649 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
03650 } else {
03651 return (*this) () (i_, j_);
03652 }
03653 }
03654
03655 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
03656 BOOST_UBLAS_INLINE
03657 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03658 typename self_type::
03659 #endif
03660 const_iterator1 begin () const {
03661 const self_type &m = (*this) ();
03662 return m.find1 (1, 0, index2 ());
03663 }
03664 BOOST_UBLAS_INLINE
03665 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03666 typename self_type::
03667 #endif
03668 const_iterator1 end () const {
03669 const self_type &m = (*this) ();
03670 return m.find1 (1, m.size1 (), index2 ());
03671 }
03672 BOOST_UBLAS_INLINE
03673 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03674 typename self_type::
03675 #endif
03676 const_reverse_iterator1 rbegin () const {
03677 return const_reverse_iterator1 (end ());
03678 }
03679 BOOST_UBLAS_INLINE
03680 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03681 typename self_type::
03682 #endif
03683 const_reverse_iterator1 rend () const {
03684 return const_reverse_iterator1 (begin ());
03685 }
03686 #endif
03687
03688
03689 BOOST_UBLAS_INLINE
03690 size_type index1 () const {
03691 if (rank_ == 1) {
03692 BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
03693 return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
03694 } else {
03695 return i_;
03696 }
03697 }
03698 BOOST_UBLAS_INLINE
03699 size_type index2 () const {
03700 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
03701 if (rank_ == 1) {
03702 BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
03703 return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
03704 } else {
03705 return j_;
03706 }
03707 }
03708
03709
03710 BOOST_UBLAS_INLINE
03711 const_iterator2 &operator = (const const_iterator2 &it) {
03712 container_const_reference<self_type>::assign (&it ());
03713 rank_ = it.rank_;
03714 i_ = it.i_;
03715 j_ = it.j_;
03716 itv_ = it.itv_;
03717 it_ = it.it_;
03718 return *this;
03719 }
03720
03721
03722 BOOST_UBLAS_INLINE
03723 bool operator == (const const_iterator2 &it) const {
03724 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
03725
03726 if (rank_ == 1 || it.rank_ == 1) {
03727 return it_ == it.it_;
03728 } else {
03729 return i_ == it.i_ && j_ == it.j_;
03730 }
03731 }
03732
03733 private:
03734 int rank_;
03735 size_type i_;
03736 size_type j_;
03737 vector_const_subiterator_type itv_;
03738 const_subiterator_type it_;
03739 };
03740
03741 BOOST_UBLAS_INLINE
03742 const_iterator2 begin2 () const {
03743 return find2 (0, 0, 0);
03744 }
03745 BOOST_UBLAS_INLINE
03746 const_iterator2 end2 () const {
03747 return find2 (0, 0, size2_);
03748 }
03749
03750 class iterator2:
03751 public container_reference<compressed_matrix>,
03752 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
03753 iterator2, value_type> {
03754 public:
03755 typedef typename compressed_matrix::value_type value_type;
03756 typedef typename compressed_matrix::difference_type difference_type;
03757 typedef typename compressed_matrix::true_reference reference;
03758 typedef typename compressed_matrix::pointer pointer;
03759
03760 typedef iterator1 dual_iterator_type;
03761 typedef reverse_iterator1 dual_reverse_iterator_type;
03762
03763
03764 BOOST_UBLAS_INLINE
03765 iterator2 ():
03766 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
03767 BOOST_UBLAS_INLINE
03768 iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
03769 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
03770
03771
03772 BOOST_UBLAS_INLINE
03773 iterator2 &operator ++ () {
03774 if (rank_ == 1 && layout_type::fast_j ())
03775 ++ it_;
03776 else {
03777 j_ = index2 () + 1;
03778 if (rank_ == 1)
03779 *this = (*this) ().find2 (rank_, i_, j_, 1);
03780 }
03781 return *this;
03782 }
03783 BOOST_UBLAS_INLINE
03784 iterator2 &operator -- () {
03785 if (rank_ == 1 && layout_type::fast_j ())
03786 -- it_;
03787 else {
03788 --j_;
03789 if (rank_ == 1)
03790 *this = (*this) ().find2 (rank_, i_, j_, -1);
03791 }
03792 return *this;
03793 }
03794
03795
03796 BOOST_UBLAS_INLINE
03797 reference operator * () const {
03798 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
03799 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
03800 if (rank_ == 1) {
03801 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
03802 } else {
03803 return (*this) ().at_element (i_, j_);
03804 }
03805 }
03806
03807 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
03808 BOOST_UBLAS_INLINE
03809 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03810 typename self_type::
03811 #endif
03812 iterator1 begin () const {
03813 self_type &m = (*this) ();
03814 return m.find1 (1, 0, index2 ());
03815 }
03816 BOOST_UBLAS_INLINE
03817 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03818 typename self_type::
03819 #endif
03820 iterator1 end () const {
03821 self_type &m = (*this) ();
03822 return m.find1 (1, m.size1 (), index2 ());
03823 }
03824 BOOST_UBLAS_INLINE
03825 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03826 typename self_type::
03827 #endif
03828 reverse_iterator1 rbegin () const {
03829 return reverse_iterator1 (end ());
03830 }
03831 BOOST_UBLAS_INLINE
03832 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
03833 typename self_type::
03834 #endif
03835 reverse_iterator1 rend () const {
03836 return reverse_iterator1 (begin ());
03837 }
03838 #endif
03839
03840
03841 BOOST_UBLAS_INLINE
03842 size_type index1 () const {
03843 if (rank_ == 1) {
03844 BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
03845 return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
03846 } else {
03847 return i_;
03848 }
03849 }
03850 BOOST_UBLAS_INLINE
03851 size_type index2 () const {
03852 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
03853 if (rank_ == 1) {
03854 BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
03855 return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
03856 } else {
03857 return j_;
03858 }
03859 }
03860
03861
03862 BOOST_UBLAS_INLINE
03863 iterator2 &operator = (const iterator2 &it) {
03864 container_reference<self_type>::assign (&it ());
03865 rank_ = it.rank_;
03866 i_ = it.i_;
03867 j_ = it.j_;
03868 itv_ = it.itv_;
03869 it_ = it.it_;
03870 return *this;
03871 }
03872
03873
03874 BOOST_UBLAS_INLINE
03875 bool operator == (const iterator2 &it) const {
03876 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
03877
03878 if (rank_ == 1 || it.rank_ == 1) {
03879 return it_ == it.it_;
03880 } else {
03881 return i_ == it.i_ && j_ == it.j_;
03882 }
03883 }
03884
03885 private:
03886 int rank_;
03887 size_type i_;
03888 size_type j_;
03889 vector_subiterator_type itv_;
03890 subiterator_type it_;
03891
03892 friend class const_iterator2;
03893 };
03894
03895 BOOST_UBLAS_INLINE
03896 iterator2 begin2 () {
03897 return find2 (0, 0, 0);
03898 }
03899 BOOST_UBLAS_INLINE
03900 iterator2 end2 () {
03901 return find2 (0, 0, size2_);
03902 }
03903
03904
03905
03906 BOOST_UBLAS_INLINE
03907 const_reverse_iterator1 rbegin1 () const {
03908 return const_reverse_iterator1 (end1 ());
03909 }
03910 BOOST_UBLAS_INLINE
03911 const_reverse_iterator1 rend1 () const {
03912 return const_reverse_iterator1 (begin1 ());
03913 }
03914
03915 BOOST_UBLAS_INLINE
03916 reverse_iterator1 rbegin1 () {
03917 return reverse_iterator1 (end1 ());
03918 }
03919 BOOST_UBLAS_INLINE
03920 reverse_iterator1 rend1 () {
03921 return reverse_iterator1 (begin1 ());
03922 }
03923
03924 BOOST_UBLAS_INLINE
03925 const_reverse_iterator2 rbegin2 () const {
03926 return const_reverse_iterator2 (end2 ());
03927 }
03928 BOOST_UBLAS_INLINE
03929 const_reverse_iterator2 rend2 () const {
03930 return const_reverse_iterator2 (begin2 ());
03931 }
03932
03933 BOOST_UBLAS_INLINE
03934 reverse_iterator2 rbegin2 () {
03935 return reverse_iterator2 (end2 ());
03936 }
03937 BOOST_UBLAS_INLINE
03938 reverse_iterator2 rend2 () {
03939 return reverse_iterator2 (begin2 ());
03940 }
03941
03942
03943 template<class Archive>
03944 void serialize(Archive & ar, const unsigned int ){
03945 serialization::collection_size_type s1 (size1_);
03946 serialization::collection_size_type s2 (size2_);
03947 ar & serialization::make_nvp("size1",s1);
03948 ar & serialization::make_nvp("size2",s2);
03949 if (Archive::is_loading::value) {
03950 size1_ = s1;
03951 size2_ = s2;
03952 }
03953 ar & serialization::make_nvp("capacity", capacity_);
03954 ar & serialization::make_nvp("filled1", filled1_);
03955 ar & serialization::make_nvp("filled2", filled2_);
03956 ar & serialization::make_nvp("index1_data", index1_data_);
03957 ar & serialization::make_nvp("index2_data", index2_data_);
03958 ar & serialization::make_nvp("value_data", value_data_);
03959 storage_invariants();
03960 }
03961
03962 private:
03963 void storage_invariants () const {
03964 BOOST_UBLAS_CHECK (layout_type::size_M (size1_, size2_) + 1 == index1_data_.size (), internal_logic ());
03965 BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ());
03966 BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
03967 BOOST_UBLAS_CHECK (filled1_ > 0 && filled1_ <= layout_type::size_M (size1_, size2_) + 1, internal_logic ());
03968 BOOST_UBLAS_CHECK (filled2_ <= capacity_, internal_logic ());
03969 BOOST_UBLAS_CHECK (index1_data_ [filled1_ - 1] == k_based (filled2_), internal_logic ());
03970 }
03971
03972 size_type size1_;
03973 size_type size2_;
03974 array_size_type capacity_;
03975 array_size_type filled1_;
03976 array_size_type filled2_;
03977 index_array_type index1_data_;
03978 index_array_type index2_data_;
03979 value_array_type value_data_;
03980 static const value_type zero_;
03981
03982 BOOST_UBLAS_INLINE
03983 static size_type zero_based (size_type k_based_index) {
03984 return k_based_index - IB;
03985 }
03986 BOOST_UBLAS_INLINE
03987 static size_type k_based (size_type zero_based_index) {
03988 return zero_based_index + IB;
03989 }
03990
03991 friend class iterator1;
03992 friend class iterator2;
03993 friend class const_iterator1;
03994 friend class const_iterator2;
03995 };
03996
03997 template<class T, class L, std::size_t IB, class IA, class TA>
03998 const typename compressed_matrix<T, L, IB, IA, TA>::value_type compressed_matrix<T, L, IB, IA, TA>::zero_ = value_type();
03999
04000
04001
04002
04003 template<class T, class L, std::size_t IB, class IA, class TA>
04004 class coordinate_matrix:
04005 public matrix_container<coordinate_matrix<T, L, IB, IA, TA> > {
04006
04007 typedef T &true_reference;
04008 typedef T *pointer;
04009 typedef const T *const_pointer;
04010 typedef L layout_type;
04011 typedef coordinate_matrix<T, L, IB, IA, TA> self_type;
04012 public:
04013 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
04014 using matrix_container<self_type>::operator ();
04015 #endif
04016
04017 typedef typename IA::value_type size_type;
04018
04019 typedef std::ptrdiff_t difference_type;
04020
04021 typedef typename IA::size_type array_size_type;
04022 typedef T value_type;
04023 typedef const T &const_reference;
04024 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
04025 typedef T &reference;
04026 #else
04027 typedef sparse_matrix_element<self_type> reference;
04028 #endif
04029 typedef IA index_array_type;
04030 typedef TA value_array_type;
04031 typedef const matrix_reference<const self_type> const_closure_type;
04032 typedef matrix_reference<self_type> closure_type;
04033 typedef coordinate_vector<T, IB, IA, TA> vector_temporary_type;
04034 typedef self_type matrix_temporary_type;
04035 typedef sparse_tag storage_category;
04036 typedef typename L::orientation_category orientation_category;
04037
04038
04039 BOOST_UBLAS_INLINE
04040 coordinate_matrix ():
04041 matrix_container<self_type> (),
04042 size1_ (0), size2_ (0), capacity_ (restrict_capacity (0)),
04043 filled_ (0), sorted_filled_ (filled_), sorted_ (true),
04044 index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) {
04045 storage_invariants ();
04046 }
04047 BOOST_UBLAS_INLINE
04048 coordinate_matrix (size_type size1, size_type size2, array_size_type non_zeros = 0):
04049 matrix_container<self_type> (),
04050 size1_ (size1), size2_ (size2), capacity_ (restrict_capacity (non_zeros)),
04051 filled_ (0), sorted_filled_ (filled_), sorted_ (true),
04052 index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) {
04053 storage_invariants ();
04054 }
04055 BOOST_UBLAS_INLINE
04056 coordinate_matrix (const coordinate_matrix &m):
04057 matrix_container<self_type> (),
04058 size1_ (m.size1_), size2_ (m.size2_), capacity_ (m.capacity_),
04059 filled_ (m.filled_), sorted_filled_ (m.sorted_filled_), sorted_ (m.sorted_),
04060 index1_data_ (m.index1_data_), index2_data_ (m.index2_data_), value_data_ (m.value_data_) {
04061 storage_invariants ();
04062 }
04063 template<class AE>
04064 BOOST_UBLAS_INLINE
04065 coordinate_matrix (const matrix_expression<AE> &ae, array_size_type non_zeros = 0):
04066 matrix_container<self_type> (),
04067 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), capacity_ (restrict_capacity (non_zeros)),
04068 filled_ (0), sorted_filled_ (filled_), sorted_ (true),
04069 index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) {
04070 storage_invariants ();
04071 matrix_assign<scalar_assign> (*this, ae);
04072 }
04073
04074
04075 BOOST_UBLAS_INLINE
04076 size_type size1 () const {
04077 return size1_;
04078 }
04079 BOOST_UBLAS_INLINE
04080 size_type size2 () const {
04081 return size2_;
04082 }
04083 BOOST_UBLAS_INLINE
04084 size_type nnz_capacity () const {
04085 return capacity_;
04086 }
04087 BOOST_UBLAS_INLINE
04088 size_type nnz () const {
04089 return filled_;
04090 }
04091
04092
04093 BOOST_UBLAS_INLINE
04094 static size_type index_base () {
04095 return IB;
04096 }
04097 BOOST_UBLAS_INLINE
04098 array_size_type filled () const {
04099 return filled_;
04100 }
04101 BOOST_UBLAS_INLINE
04102 const index_array_type &index1_data () const {
04103 return index1_data_;
04104 }
04105 BOOST_UBLAS_INLINE
04106 const index_array_type &index2_data () const {
04107 return index2_data_;
04108 }
04109 BOOST_UBLAS_INLINE
04110 const value_array_type &value_data () const {
04111 return value_data_;
04112 }
04113 BOOST_UBLAS_INLINE
04114 void set_filled (const array_size_type &filled) {
04115
04116 if (sorted_ && filled < filled_)
04117 sorted_filled_ = filled;
04118 else
04119 sorted_ = (sorted_filled_ == filled);
04120 filled_ = filled;
04121 storage_invariants ();
04122 }
04123 BOOST_UBLAS_INLINE
04124 index_array_type &index1_data () {
04125 return index1_data_;
04126 }
04127 BOOST_UBLAS_INLINE
04128 index_array_type &index2_data () {
04129 return index2_data_;
04130 }
04131 BOOST_UBLAS_INLINE
04132 value_array_type &value_data () {
04133 return value_data_;
04134 }
04135
04136
04137 private:
04138 BOOST_UBLAS_INLINE
04139 array_size_type restrict_capacity (array_size_type non_zeros) const {
04140
04141 non_zeros = (std::max) (non_zeros, array_size_type((std::min) (size1_, size2_)));
04142
04143 return non_zeros;
04144 }
04145 public:
04146 BOOST_UBLAS_INLINE
04147 void resize (size_type size1, size_type size2, bool preserve = true) {
04148
04149 BOOST_UBLAS_CHECK (!preserve, internal_logic ());
04150 size1_ = size1;
04151 size2_ = size2;
04152 capacity_ = restrict_capacity (capacity_);
04153 index1_data_.resize (capacity_);
04154 index2_data_.resize (capacity_);
04155 value_data_.resize (capacity_);
04156 filled_ = 0;
04157 sorted_filled_ = filled_;
04158 sorted_ = true;
04159 storage_invariants ();
04160 }
04161
04162
04163 BOOST_UBLAS_INLINE
04164 void reserve (array_size_type non_zeros, bool preserve = true) {
04165 sort ();
04166 capacity_ = restrict_capacity (non_zeros);
04167 if (preserve) {
04168 index1_data_.resize (capacity_, size_type ());
04169 index2_data_.resize (capacity_, size_type ());
04170 value_data_.resize (capacity_, value_type ());
04171 filled_ = (std::min) (capacity_, filled_);
04172 }
04173 else {
04174 index1_data_.resize (capacity_);
04175 index2_data_.resize (capacity_);
04176 value_data_.resize (capacity_);
04177 filled_ = 0;
04178 }
04179 sorted_filled_ = filled_;
04180 storage_invariants ();
04181 }
04182
04183
04184 BOOST_UBLAS_INLINE
04185 pointer find_element (size_type i, size_type j) {
04186 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
04187 }
04188 BOOST_UBLAS_INLINE
04189 const_pointer find_element (size_type i, size_type j) const {
04190 sort ();
04191 size_type element1 (layout_type::index_M (i, j));
04192 size_type element2 (layout_type::index_m (i, j));
04193 vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
04194 vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
04195 if (itv_begin == itv_end)
04196 return 0;
04197 const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
04198 const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
04199 const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
04200 if (it == it_end || *it != k_based (element2))
04201 return 0;
04202 return &value_data_ [it - index2_data_.begin ()];
04203 }
04204
04205
04206 BOOST_UBLAS_INLINE
04207 const_reference operator () (size_type i, size_type j) const {
04208 const_pointer p = find_element (i, j);
04209 if (p)
04210 return *p;
04211 else
04212 return zero_;
04213 }
04214 BOOST_UBLAS_INLINE
04215 reference operator () (size_type i, size_type j) {
04216 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
04217 pointer p = find_element (i, j);
04218 if (p)
04219 return *p;
04220 else
04221 return insert_element (i, j, value_type());
04222 #else
04223 return reference (*this, i, j);
04224 #endif
04225 }
04226
04227
04228 BOOST_UBLAS_INLINE
04229 void append_element (size_type i, size_type j, const_reference t) {
04230 if (filled_ >= capacity_)
04231 reserve (2 * filled_, true);
04232 BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
04233 size_type element1 = layout_type::index_M (i, j);
04234 size_type element2 = layout_type::index_m (i, j);
04235 index1_data_ [filled_] = k_based (element1);
04236 index2_data_ [filled_] = k_based (element2);
04237 value_data_ [filled_] = t;
04238 ++ filled_;
04239 sorted_ = false;
04240 storage_invariants ();
04241 }
04242 BOOST_UBLAS_INLINE
04243 true_reference insert_element (size_type i, size_type j, const_reference t) {
04244 BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ());
04245 append_element (i, j, t);
04246 return value_data_ [filled_ - 1];
04247 }
04248 BOOST_UBLAS_INLINE
04249 void erase_element (size_type i, size_type j) {
04250 size_type element1 = layout_type::index_M (i, j);
04251 size_type element2 = layout_type::index_m (i, j);
04252 sort ();
04253 vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
04254 vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
04255 subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
04256 subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
04257 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
04258 if (it != it_end && *it == k_based (element2)) {
04259 typename std::iterator_traits<subiterator_type>::difference_type n = it - index2_data_.begin ();
04260 vector_subiterator_type itv (index1_data_.begin () + n);
04261 std::copy (itv + 1, index1_data_.begin () + filled_, itv);
04262 std::copy (it + 1, index2_data_.begin () + filled_, it);
04263 typename value_array_type::iterator itt (value_data_.begin () + n);
04264 std::copy (itt + 1, value_data_.begin () + filled_, itt);
04265 -- filled_;
04266 sorted_filled_ = filled_;
04267 }
04268 storage_invariants ();
04269 }
04270
04271
04272 BOOST_UBLAS_INLINE
04273 void clear () {
04274 filled_ = 0;
04275 sorted_filled_ = filled_;
04276 sorted_ = true;
04277 storage_invariants ();
04278 }
04279
04280
04281 BOOST_UBLAS_INLINE
04282 coordinate_matrix &operator = (const coordinate_matrix &m) {
04283 if (this != &m) {
04284 size1_ = m.size1_;
04285 size2_ = m.size2_;
04286 capacity_ = m.capacity_;
04287 filled_ = m.filled_;
04288 sorted_filled_ = m.sorted_filled_;
04289 sorted_ = m.sorted_;
04290 index1_data_ = m.index1_data_;
04291 index2_data_ = m.index2_data_;
04292 value_data_ = m.value_data_;
04293 BOOST_UBLAS_CHECK (capacity_ == index1_data_.size (), internal_logic ());
04294 BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ());
04295 BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
04296 }
04297 storage_invariants ();
04298 return *this;
04299 }
04300 template<class C>
04301 BOOST_UBLAS_INLINE
04302 coordinate_matrix &operator = (const matrix_container<C> &m) {
04303 resize (m ().size1 (), m ().size2 (), false);
04304 assign (m);
04305 return *this;
04306 }
04307 BOOST_UBLAS_INLINE
04308 coordinate_matrix &assign_temporary (coordinate_matrix &m) {
04309 swap (m);
04310 return *this;
04311 }
04312 template<class AE>
04313 BOOST_UBLAS_INLINE
04314 coordinate_matrix &operator = (const matrix_expression<AE> &ae) {
04315 self_type temporary (ae, capacity_);
04316 return assign_temporary (temporary);
04317 }
04318 template<class AE>
04319 BOOST_UBLAS_INLINE
04320 coordinate_matrix &assign (const matrix_expression<AE> &ae) {
04321 matrix_assign<scalar_assign> (*this, ae);
04322 return *this;
04323 }
04324 template<class AE>
04325 BOOST_UBLAS_INLINE
04326 coordinate_matrix& operator += (const matrix_expression<AE> &ae) {
04327 self_type temporary (*this + ae, capacity_);
04328 return assign_temporary (temporary);
04329 }
04330 template<class C>
04331 BOOST_UBLAS_INLINE
04332 coordinate_matrix &operator += (const matrix_container<C> &m) {
04333 plus_assign (m);
04334 return *this;
04335 }
04336 template<class AE>
04337 BOOST_UBLAS_INLINE
04338 coordinate_matrix &plus_assign (const matrix_expression<AE> &ae) {
04339 matrix_assign<scalar_plus_assign> (*this, ae);
04340 return *this;
04341 }
04342 template<class AE>
04343 BOOST_UBLAS_INLINE
04344 coordinate_matrix& operator -= (const matrix_expression<AE> &ae) {
04345 self_type temporary (*this - ae, capacity_);
04346 return assign_temporary (temporary);
04347 }
04348 template<class C>
04349 BOOST_UBLAS_INLINE
04350 coordinate_matrix &operator -= (const matrix_container<C> &m) {
04351 minus_assign (m);
04352 return *this;
04353 }
04354 template<class AE>
04355 BOOST_UBLAS_INLINE
04356 coordinate_matrix &minus_assign (const matrix_expression<AE> &ae) {
04357 matrix_assign<scalar_minus_assign> (*this, ae);
04358 return *this;
04359 }
04360 template<class AT>
04361 BOOST_UBLAS_INLINE
04362 coordinate_matrix& operator *= (const AT &at) {
04363 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
04364 return *this;
04365 }
04366 template<class AT>
04367 BOOST_UBLAS_INLINE
04368 coordinate_matrix& operator /= (const AT &at) {
04369 matrix_assign_scalar<scalar_divides_assign> (*this, at);
04370 return *this;
04371 }
04372
04373
04374 BOOST_UBLAS_INLINE
04375 void swap (coordinate_matrix &m) {
04376 if (this != &m) {
04377 std::swap (size1_, m.size1_);
04378 std::swap (size2_, m.size2_);
04379 std::swap (capacity_, m.capacity_);
04380 std::swap (filled_, m.filled_);
04381 std::swap (sorted_filled_, m.sorted_filled_);
04382 std::swap (sorted_, m.sorted_);
04383 index1_data_.swap (m.index1_data_);
04384 index2_data_.swap (m.index2_data_);
04385 value_data_.swap (m.value_data_);
04386 }
04387 storage_invariants ();
04388 }
04389 BOOST_UBLAS_INLINE
04390 friend void swap (coordinate_matrix &m1, coordinate_matrix &m2) {
04391 m1.swap (m2);
04392 }
04393
04394
04395 BOOST_UBLAS_INLINE
04396 void sort () const {
04397 if (! sorted_ && filled_ > 0) {
04398 typedef index_triple_array<index_array_type, index_array_type, value_array_type> array_triple;
04399 array_triple ita (filled_, index1_data_, index2_data_, value_data_);
04400 const typename array_triple::iterator iunsorted = ita.begin () + sorted_filled_;
04401
04402 std::sort (iunsorted, ita.end ());
04403 std::inplace_merge (ita.begin (), iunsorted, ita.end ());
04404
04405
04406 array_size_type filled = 0;
04407 for (array_size_type i = 1; i < filled_; ++ i) {
04408 if (index1_data_ [filled] != index1_data_ [i] ||
04409 index2_data_ [filled] != index2_data_ [i]) {
04410 ++ filled;
04411 if (filled != i) {
04412 index1_data_ [filled] = index1_data_ [i];
04413 index2_data_ [filled] = index2_data_ [i];
04414 value_data_ [filled] = value_data_ [i];
04415 }
04416 } else {
04417 value_data_ [filled] += value_data_ [i];
04418 }
04419 }
04420 filled_ = filled + 1;
04421 sorted_filled_ = filled_;
04422 sorted_ = true;
04423 storage_invariants ();
04424 }
04425 }
04426
04427
04428 BOOST_UBLAS_INLINE
04429 void push_back (size_type i, size_type j, const_reference t) {
04430 size_type element1 = layout_type::index_M (i, j);
04431 size_type element2 = layout_type::index_m (i, j);
04432
04433 BOOST_UBLAS_CHECK (sorted_ &&
04434 (filled_ == 0 ||
04435 index1_data_ [filled_ - 1] < k_based (element1) ||
04436 (index1_data_ [filled_ - 1] == k_based (element1) && index2_data_ [filled_ - 1] < k_based (element2)))
04437 , external_logic ());
04438 if (filled_ >= capacity_)
04439 reserve (2 * filled_, true);
04440 BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
04441 index1_data_ [filled_] = k_based (element1);
04442 index2_data_ [filled_] = k_based (element2);
04443 value_data_ [filled_] = t;
04444 ++ filled_;
04445 sorted_filled_ = filled_;
04446 storage_invariants ();
04447 }
04448 BOOST_UBLAS_INLINE
04449 void pop_back () {
04450
04451 BOOST_UBLAS_CHECK (filled_ > 0, external_logic ());
04452 -- filled_;
04453 sorted_filled_ = (std::min) (sorted_filled_, filled_);
04454 sorted_ = sorted_filled_ = filled_;
04455 storage_invariants ();
04456 }
04457
04458
04459 private:
04460
04461 typedef typename IA::const_iterator vector_const_subiterator_type;
04462 typedef typename IA::iterator vector_subiterator_type;
04463 typedef typename IA::const_iterator const_subiterator_type;
04464 typedef typename IA::iterator subiterator_type;
04465
04466 BOOST_UBLAS_INLINE
04467 true_reference at_element (size_type i, size_type j) {
04468 pointer p = find_element (i, j);
04469 BOOST_UBLAS_CHECK (p, bad_index ());
04470 return *p;
04471 }
04472
04473 public:
04474 class const_iterator1;
04475 class iterator1;
04476 class const_iterator2;
04477 class iterator2;
04478 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
04479 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
04480 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
04481 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
04482
04483
04484
04485 const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
04486 sort ();
04487 for (;;) {
04488 size_type address1 (layout_type::index_M (i, j));
04489 size_type address2 (layout_type::index_m (i, j));
04490 vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
04491 vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
04492
04493 const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
04494 const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
04495
04496 const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
04497 vector_const_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
04498 if (rank == 0)
04499 return const_iterator1 (*this, rank, i, j, itv, it);
04500 if (it != it_end && zero_based (*it) == address2)
04501 return const_iterator1 (*this, rank, i, j, itv, it);
04502 if (direction > 0) {
04503 if (layout_type::fast_i ()) {
04504 if (it == it_end)
04505 return const_iterator1 (*this, rank, i, j, itv, it);
04506 i = zero_based (*it);
04507 } else {
04508 if (i >= size1_)
04509 return const_iterator1 (*this, rank, i, j, itv, it);
04510 ++ i;
04511 }
04512 } else {
04513 if (layout_type::fast_i ()) {
04514 if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
04515 return const_iterator1 (*this, rank, i, j, itv, it);
04516 i = zero_based (*(it - 1));
04517 } else {
04518 if (i == 0)
04519 return const_iterator1 (*this, rank, i, j, itv, it);
04520 -- i;
04521 }
04522 }
04523 }
04524 }
04525
04526 iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
04527 sort ();
04528 for (;;) {
04529 size_type address1 (layout_type::index_M (i, j));
04530 size_type address2 (layout_type::index_m (i, j));
04531 vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
04532 vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
04533
04534 subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
04535 subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
04536
04537 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
04538 vector_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
04539 if (rank == 0)
04540 return iterator1 (*this, rank, i, j, itv, it);
04541 if (it != it_end && zero_based (*it) == address2)
04542 return iterator1 (*this, rank, i, j, itv, it);
04543 if (direction > 0) {
04544 if (layout_type::fast_i ()) {
04545 if (it == it_end)
04546 return iterator1 (*this, rank, i, j, itv, it);
04547 i = zero_based (*it);
04548 } else {
04549 if (i >= size1_)
04550 return iterator1 (*this, rank, i, j, itv, it);
04551 ++ i;
04552 }
04553 } else {
04554 if (layout_type::fast_i ()) {
04555 if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
04556 return iterator1 (*this, rank, i, j, itv, it);
04557 i = zero_based (*(it - 1));
04558 } else {
04559 if (i == 0)
04560 return iterator1 (*this, rank, i, j, itv, it);
04561 -- i;
04562 }
04563 }
04564 }
04565 }
04566
04567 const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
04568 sort ();
04569 for (;;) {
04570 size_type address1 (layout_type::index_M (i, j));
04571 size_type address2 (layout_type::index_m (i, j));
04572 vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
04573 vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
04574
04575 const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
04576 const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
04577
04578 const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
04579 vector_const_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
04580 if (rank == 0)
04581 return const_iterator2 (*this, rank, i, j, itv, it);
04582 if (it != it_end && zero_based (*it) == address2)
04583 return const_iterator2 (*this, rank, i, j, itv, it);
04584 if (direction > 0) {
04585 if (layout_type::fast_j ()) {
04586 if (it == it_end)
04587 return const_iterator2 (*this, rank, i, j, itv, it);
04588 j = zero_based (*it);
04589 } else {
04590 if (j >= size2_)
04591 return const_iterator2 (*this, rank, i, j, itv, it);
04592 ++ j;
04593 }
04594 } else {
04595 if (layout_type::fast_j ()) {
04596 if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
04597 return const_iterator2 (*this, rank, i, j, itv, it);
04598 j = zero_based (*(it - 1));
04599 } else {
04600 if (j == 0)
04601 return const_iterator2 (*this, rank, i, j, itv, it);
04602 -- j;
04603 }
04604 }
04605 }
04606 }
04607
04608 iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
04609 sort ();
04610 for (;;) {
04611 size_type address1 (layout_type::index_M (i, j));
04612 size_type address2 (layout_type::index_m (i, j));
04613 vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
04614 vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
04615
04616 subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
04617 subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
04618
04619 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
04620 vector_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
04621 if (rank == 0)
04622 return iterator2 (*this, rank, i, j, itv, it);
04623 if (it != it_end && zero_based (*it) == address2)
04624 return iterator2 (*this, rank, i, j, itv, it);
04625 if (direction > 0) {
04626 if (layout_type::fast_j ()) {
04627 if (it == it_end)
04628 return iterator2 (*this, rank, i, j, itv, it);
04629 j = zero_based (*it);
04630 } else {
04631 if (j >= size2_)
04632 return iterator2 (*this, rank, i, j, itv, it);
04633 ++ j;
04634 }
04635 } else {
04636 if (layout_type::fast_j ()) {
04637 if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
04638 return iterator2 (*this, rank, i, j, itv, it);
04639 j = zero_based (*(it - 1));
04640 } else {
04641 if (j == 0)
04642 return iterator2 (*this, rank, i, j, itv, it);
04643 -- j;
04644 }
04645 }
04646 }
04647 }
04648
04649
04650 class const_iterator1:
04651 public container_const_reference<coordinate_matrix>,
04652 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
04653 const_iterator1, value_type> {
04654 public:
04655 typedef typename coordinate_matrix::value_type value_type;
04656 typedef typename coordinate_matrix::difference_type difference_type;
04657 typedef typename coordinate_matrix::const_reference reference;
04658 typedef const typename coordinate_matrix::pointer pointer;
04659
04660 typedef const_iterator2 dual_iterator_type;
04661 typedef const_reverse_iterator2 dual_reverse_iterator_type;
04662
04663
04664 BOOST_UBLAS_INLINE
04665 const_iterator1 ():
04666 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
04667 BOOST_UBLAS_INLINE
04668 const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type &itv, const const_subiterator_type &it):
04669 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
04670 BOOST_UBLAS_INLINE
04671 const_iterator1 (const iterator1 &it):
04672 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
04673
04674
04675 BOOST_UBLAS_INLINE
04676 const_iterator1 &operator ++ () {
04677 if (rank_ == 1 && layout_type::fast_i ())
04678 ++ it_;
04679 else {
04680 i_ = index1 () + 1;
04681 if (rank_ == 1)
04682 *this = (*this) ().find1 (rank_, i_, j_, 1);
04683 }
04684 return *this;
04685 }
04686 BOOST_UBLAS_INLINE
04687 const_iterator1 &operator -- () {
04688 if (rank_ == 1 && layout_type::fast_i ())
04689 -- it_;
04690 else {
04691 i_ = index1 () - 1;
04692 if (rank_ == 1)
04693 *this = (*this) ().find1 (rank_, i_, j_, -1);
04694 }
04695 return *this;
04696 }
04697
04698
04699 BOOST_UBLAS_INLINE
04700 const_reference operator * () const {
04701 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
04702 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
04703 if (rank_ == 1) {
04704 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
04705 } else {
04706 return (*this) () (i_, j_);
04707 }
04708 }
04709
04710 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
04711 BOOST_UBLAS_INLINE
04712 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04713 typename self_type::
04714 #endif
04715 const_iterator2 begin () const {
04716 const self_type &m = (*this) ();
04717 return m.find2 (1, index1 (), 0);
04718 }
04719 BOOST_UBLAS_INLINE
04720 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04721 typename self_type::
04722 #endif
04723 const_iterator2 end () const {
04724 const self_type &m = (*this) ();
04725 return m.find2 (1, index1 (), m.size2 ());
04726 }
04727 BOOST_UBLAS_INLINE
04728 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04729 typename self_type::
04730 #endif
04731 const_reverse_iterator2 rbegin () const {
04732 return const_reverse_iterator2 (end ());
04733 }
04734 BOOST_UBLAS_INLINE
04735 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04736 typename self_type::
04737 #endif
04738 const_reverse_iterator2 rend () const {
04739 return const_reverse_iterator2 (begin ());
04740 }
04741 #endif
04742
04743
04744 BOOST_UBLAS_INLINE
04745 size_type index1 () const {
04746 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
04747 if (rank_ == 1) {
04748 BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
04749 return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
04750 } else {
04751 return i_;
04752 }
04753 }
04754 BOOST_UBLAS_INLINE
04755 size_type index2 () const {
04756 if (rank_ == 1) {
04757 BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
04758 return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
04759 } else {
04760 return j_;
04761 }
04762 }
04763
04764
04765 BOOST_UBLAS_INLINE
04766 const_iterator1 &operator = (const const_iterator1 &it) {
04767 container_const_reference<self_type>::assign (&it ());
04768 rank_ = it.rank_;
04769 i_ = it.i_;
04770 j_ = it.j_;
04771 itv_ = it.itv_;
04772 it_ = it.it_;
04773 return *this;
04774 }
04775
04776
04777 BOOST_UBLAS_INLINE
04778 bool operator == (const const_iterator1 &it) const {
04779 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
04780
04781 if (rank_ == 1 || it.rank_ == 1) {
04782 return it_ == it.it_;
04783 } else {
04784 return i_ == it.i_ && j_ == it.j_;
04785 }
04786 }
04787
04788 private:
04789 int rank_;
04790 size_type i_;
04791 size_type j_;
04792 vector_const_subiterator_type itv_;
04793 const_subiterator_type it_;
04794 };
04795
04796 BOOST_UBLAS_INLINE
04797 const_iterator1 begin1 () const {
04798 return find1 (0, 0, 0);
04799 }
04800 BOOST_UBLAS_INLINE
04801 const_iterator1 end1 () const {
04802 return find1 (0, size1_, 0);
04803 }
04804
04805 class iterator1:
04806 public container_reference<coordinate_matrix>,
04807 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
04808 iterator1, value_type> {
04809 public:
04810 typedef typename coordinate_matrix::value_type value_type;
04811 typedef typename coordinate_matrix::difference_type difference_type;
04812 typedef typename coordinate_matrix::true_reference reference;
04813 typedef typename coordinate_matrix::pointer pointer;
04814
04815 typedef iterator2 dual_iterator_type;
04816 typedef reverse_iterator2 dual_reverse_iterator_type;
04817
04818
04819 BOOST_UBLAS_INLINE
04820 iterator1 ():
04821 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
04822 BOOST_UBLAS_INLINE
04823 iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
04824 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
04825
04826
04827 BOOST_UBLAS_INLINE
04828 iterator1 &operator ++ () {
04829 if (rank_ == 1 && layout_type::fast_i ())
04830 ++ it_;
04831 else {
04832 i_ = index1 () + 1;
04833 if (rank_ == 1)
04834 *this = (*this) ().find1 (rank_, i_, j_, 1);
04835 }
04836 return *this;
04837 }
04838 BOOST_UBLAS_INLINE
04839 iterator1 &operator -- () {
04840 if (rank_ == 1 && layout_type::fast_i ())
04841 -- it_;
04842 else {
04843 i_ = index1 () - 1;
04844 if (rank_ == 1)
04845 *this = (*this) ().find1 (rank_, i_, j_, -1);
04846 }
04847 return *this;
04848 }
04849
04850
04851 BOOST_UBLAS_INLINE
04852 reference operator * () const {
04853 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
04854 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
04855 if (rank_ == 1) {
04856 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
04857 } else {
04858 return (*this) ().at_element (i_, j_);
04859 }
04860 }
04861
04862 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
04863 BOOST_UBLAS_INLINE
04864 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04865 typename self_type::
04866 #endif
04867 iterator2 begin () const {
04868 self_type &m = (*this) ();
04869 return m.find2 (1, index1 (), 0);
04870 }
04871 BOOST_UBLAS_INLINE
04872 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04873 typename self_type::
04874 #endif
04875 iterator2 end () const {
04876 self_type &m = (*this) ();
04877 return m.find2 (1, index1 (), m.size2 ());
04878 }
04879 BOOST_UBLAS_INLINE
04880 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04881 typename self_type::
04882 #endif
04883 reverse_iterator2 rbegin () const {
04884 return reverse_iterator2 (end ());
04885 }
04886 BOOST_UBLAS_INLINE
04887 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
04888 typename self_type::
04889 #endif
04890 reverse_iterator2 rend () const {
04891 return reverse_iterator2 (begin ());
04892 }
04893 #endif
04894
04895
04896 BOOST_UBLAS_INLINE
04897 size_type index1 () const {
04898 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
04899 if (rank_ == 1) {
04900 BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
04901 return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
04902 } else {
04903 return i_;
04904 }
04905 }
04906 BOOST_UBLAS_INLINE
04907 size_type index2 () const {
04908 if (rank_ == 1) {
04909 BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
04910 return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
04911 } else {
04912 return j_;
04913 }
04914 }
04915
04916
04917 BOOST_UBLAS_INLINE
04918 iterator1 &operator = (const iterator1 &it) {
04919 container_reference<self_type>::assign (&it ());
04920 rank_ = it.rank_;
04921 i_ = it.i_;
04922 j_ = it.j_;
04923 itv_ = it.itv_;
04924 it_ = it.it_;
04925 return *this;
04926 }
04927
04928
04929 BOOST_UBLAS_INLINE
04930 bool operator == (const iterator1 &it) const {
04931 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
04932
04933 if (rank_ == 1 || it.rank_ == 1) {
04934 return it_ == it.it_;
04935 } else {
04936 return i_ == it.i_ && j_ == it.j_;
04937 }
04938 }
04939
04940 private:
04941 int rank_;
04942 size_type i_;
04943 size_type j_;
04944 vector_subiterator_type itv_;
04945 subiterator_type it_;
04946
04947 friend class const_iterator1;
04948 };
04949
04950 BOOST_UBLAS_INLINE
04951 iterator1 begin1 () {
04952 return find1 (0, 0, 0);
04953 }
04954 BOOST_UBLAS_INLINE
04955 iterator1 end1 () {
04956 return find1 (0, size1_, 0);
04957 }
04958
04959 class const_iterator2:
04960 public container_const_reference<coordinate_matrix>,
04961 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
04962 const_iterator2, value_type> {
04963 public:
04964 typedef typename coordinate_matrix::value_type value_type;
04965 typedef typename coordinate_matrix::difference_type difference_type;
04966 typedef typename coordinate_matrix::const_reference reference;
04967 typedef const typename coordinate_matrix::pointer pointer;
04968
04969 typedef const_iterator1 dual_iterator_type;
04970 typedef const_reverse_iterator1 dual_reverse_iterator_type;
04971
04972
04973 BOOST_UBLAS_INLINE
04974 const_iterator2 ():
04975 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
04976 BOOST_UBLAS_INLINE
04977 const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const vector_const_subiterator_type itv, const const_subiterator_type &it):
04978 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
04979 BOOST_UBLAS_INLINE
04980 const_iterator2 (const iterator2 &it):
04981 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
04982
04983
04984 BOOST_UBLAS_INLINE
04985 const_iterator2 &operator ++ () {
04986 if (rank_ == 1 && layout_type::fast_j ())
04987 ++ it_;
04988 else {
04989 j_ = index2 () + 1;
04990 if (rank_ == 1)
04991 *this = (*this) ().find2 (rank_, i_, j_, 1);
04992 }
04993 return *this;
04994 }
04995 BOOST_UBLAS_INLINE
04996 const_iterator2 &operator -- () {
04997 if (rank_ == 1 && layout_type::fast_j ())
04998 -- it_;
04999 else {
05000 j_ = index2 () - 1;
05001 if (rank_ == 1)
05002 *this = (*this) ().find2 (rank_, i_, j_, -1);
05003 }
05004 return *this;
05005 }
05006
05007
05008 BOOST_UBLAS_INLINE
05009 const_reference operator * () const {
05010 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
05011 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
05012 if (rank_ == 1) {
05013 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
05014 } else {
05015 return (*this) () (i_, j_);
05016 }
05017 }
05018
05019 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
05020 BOOST_UBLAS_INLINE
05021 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
05022 typename self_type::
05023 #endif
05024 const_iterator1 begin () const {
05025 const self_type &m = (*this) ();
05026 return m.find1 (1, 0, index2 ());
05027 }
05028 BOOST_UBLAS_INLINE
05029 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
05030 typename self_type::
05031 #endif
05032 const_iterator1 end () const {
05033 const self_type &m = (*this) ();
05034 return m.find1 (1, m.size1 (), index2 ());
05035 }
05036 BOOST_UBLAS_INLINE
05037 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
05038 typename self_type::
05039 #endif
05040 const_reverse_iterator1 rbegin () const {
05041 return const_reverse_iterator1 (end ());
05042 }
05043 BOOST_UBLAS_INLINE
05044 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
05045 typename self_type::
05046 #endif
05047 const_reverse_iterator1 rend () const {
05048 return const_reverse_iterator1 (begin ());
05049 }
05050 #endif
05051
05052
05053 BOOST_UBLAS_INLINE
05054 size_type index1 () const {
05055 if (rank_ == 1) {
05056 BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
05057 return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
05058 } else {
05059 return i_;
05060 }
05061 }
05062 BOOST_UBLAS_INLINE
05063 size_type index2 () const {
05064 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
05065 if (rank_ == 1) {
05066 BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
05067 return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
05068 } else {
05069 return j_;
05070 }
05071 }
05072
05073
05074 BOOST_UBLAS_INLINE
05075 const_iterator2 &operator = (const const_iterator2 &it) {
05076 container_const_reference<self_type>::assign (&it ());
05077 rank_ = it.rank_;
05078 i_ = it.i_;
05079 j_ = it.j_;
05080 itv_ = it.itv_;
05081 it_ = it.it_;
05082 return *this;
05083 }
05084
05085
05086 BOOST_UBLAS_INLINE
05087 bool operator == (const const_iterator2 &it) const {
05088 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
05089
05090 if (rank_ == 1 || it.rank_ == 1) {
05091 return it_ == it.it_;
05092 } else {
05093 return i_ == it.i_ && j_ == it.j_;
05094 }
05095 }
05096
05097 private:
05098 int rank_;
05099 size_type i_;
05100 size_type j_;
05101 vector_const_subiterator_type itv_;
05102 const_subiterator_type it_;
05103 };
05104
05105 BOOST_UBLAS_INLINE
05106 const_iterator2 begin2 () const {
05107 return find2 (0, 0, 0);
05108 }
05109 BOOST_UBLAS_INLINE
05110 const_iterator2 end2 () const {
05111 return find2 (0, 0, size2_);
05112 }
05113
05114 class iterator2:
05115 public container_reference<coordinate_matrix>,
05116 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
05117 iterator2, value_type> {
05118 public:
05119 typedef typename coordinate_matrix::value_type value_type;
05120 typedef typename coordinate_matrix::difference_type difference_type;
05121 typedef typename coordinate_matrix::true_reference reference;
05122 typedef typename coordinate_matrix::pointer pointer;
05123
05124 typedef iterator1 dual_iterator_type;
05125 typedef reverse_iterator1 dual_reverse_iterator_type;
05126
05127
05128 BOOST_UBLAS_INLINE
05129 iterator2 ():
05130 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
05131 BOOST_UBLAS_INLINE
05132 iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
05133 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
05134
05135
05136 BOOST_UBLAS_INLINE
05137 iterator2 &operator ++ () {
05138 if (rank_ == 1 && layout_type::fast_j ())
05139 ++ it_;
05140 else {
05141 j_ = index2 () + 1;
05142 if (rank_ == 1)
05143 *this = (*this) ().find2 (rank_, i_, j_, 1);
05144 }
05145 return *this;
05146 }
05147 BOOST_UBLAS_INLINE
05148 iterator2 &operator -- () {
05149 if (rank_ == 1 && layout_type::fast_j ())
05150 -- it_;
05151 else {
05152 j_ = index2 ();
05153 if (rank_ == 1)
05154 *this = (*this) ().find2 (rank_, i_, j_, -1);
05155 }
05156 return *this;
05157 }
05158
05159
05160 BOOST_UBLAS_INLINE
05161 reference operator * () const {
05162 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
05163 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
05164 if (rank_ == 1) {
05165 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
05166 } else {
05167 return (*this) ().at_element (i_, j_);
05168 }
05169 }
05170
05171 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
05172 BOOST_UBLAS_INLINE
05173 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
05174 typename self_type::
05175 #endif
05176 iterator1 begin () const {
05177 self_type &m = (*this) ();
05178 return m.find1 (1, 0, index2 ());
05179 }
05180 BOOST_UBLAS_INLINE
05181 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
05182 typename self_type::
05183 #endif
05184 iterator1 end () const {
05185 self_type &m = (*this) ();
05186 return m.find1 (1, m.size1 (), index2 ());
05187 }
05188 BOOST_UBLAS_INLINE
05189 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
05190 typename self_type::
05191 #endif
05192 reverse_iterator1 rbegin () const {
05193 return reverse_iterator1 (end ());
05194 }
05195 BOOST_UBLAS_INLINE
05196 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
05197 typename self_type::
05198 #endif
05199 reverse_iterator1 rend () const {
05200 return reverse_iterator1 (begin ());
05201 }
05202 #endif
05203
05204
05205 BOOST_UBLAS_INLINE
05206 size_type index1 () const {
05207 if (rank_ == 1) {
05208 BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
05209 return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
05210 } else {
05211 return i_;
05212 }
05213 }
05214 BOOST_UBLAS_INLINE
05215 size_type index2 () const {
05216 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
05217 if (rank_ == 1) {
05218 BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
05219 return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
05220 } else {
05221 return j_;
05222 }
05223 }
05224
05225
05226 BOOST_UBLAS_INLINE
05227 iterator2 &operator = (const iterator2 &it) {
05228 container_reference<self_type>::assign (&it ());
05229 rank_ = it.rank_;
05230 i_ = it.i_;
05231 j_ = it.j_;
05232 itv_ = it.itv_;
05233 it_ = it.it_;
05234 return *this;
05235 }
05236
05237
05238 BOOST_UBLAS_INLINE
05239 bool operator == (const iterator2 &it) const {
05240 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
05241
05242 if (rank_ == 1 || it.rank_ == 1) {
05243 return it_ == it.it_;
05244 } else {
05245 return i_ == it.i_ && j_ == it.j_;
05246 }
05247 }
05248
05249 private:
05250 int rank_;
05251 size_type i_;
05252 size_type j_;
05253 vector_subiterator_type itv_;
05254 subiterator_type it_;
05255
05256 friend class const_iterator2;
05257 };
05258
05259 BOOST_UBLAS_INLINE
05260 iterator2 begin2 () {
05261 return find2 (0, 0, 0);
05262 }
05263 BOOST_UBLAS_INLINE
05264 iterator2 end2 () {
05265 return find2 (0, 0, size2_);
05266 }
05267
05268
05269
05270 BOOST_UBLAS_INLINE
05271 const_reverse_iterator1 rbegin1 () const {
05272 return const_reverse_iterator1 (end1 ());
05273 }
05274 BOOST_UBLAS_INLINE
05275 const_reverse_iterator1 rend1 () const {
05276 return const_reverse_iterator1 (begin1 ());
05277 }
05278
05279 BOOST_UBLAS_INLINE
05280 reverse_iterator1 rbegin1 () {
05281 return reverse_iterator1 (end1 ());
05282 }
05283 BOOST_UBLAS_INLINE
05284 reverse_iterator1 rend1 () {
05285 return reverse_iterator1 (begin1 ());
05286 }
05287
05288 BOOST_UBLAS_INLINE
05289 const_reverse_iterator2 rbegin2 () const {
05290 return const_reverse_iterator2 (end2 ());
05291 }
05292 BOOST_UBLAS_INLINE
05293 const_reverse_iterator2 rend2 () const {
05294 return const_reverse_iterator2 (begin2 ());
05295 }
05296
05297 BOOST_UBLAS_INLINE
05298 reverse_iterator2 rbegin2 () {
05299 return reverse_iterator2 (end2 ());
05300 }
05301 BOOST_UBLAS_INLINE
05302 reverse_iterator2 rend2 () {
05303 return reverse_iterator2 (begin2 ());
05304 }
05305
05306
05307 template<class Archive>
05308 void serialize(Archive & ar, const unsigned int ){
05309 serialization::collection_size_type s1 (size1_);
05310 serialization::collection_size_type s2 (size2_);
05311 ar & serialization::make_nvp("size1",s1);
05312 ar & serialization::make_nvp("size2",s2);
05313 if (Archive::is_loading::value) {
05314 size1_ = s1;
05315 size2_ = s2;
05316 }
05317 ar & serialization::make_nvp("capacity", capacity_);
05318 ar & serialization::make_nvp("filled", filled_);
05319 ar & serialization::make_nvp("sorted_filled", sorted_filled_);
05320 ar & serialization::make_nvp("sorted", sorted_);
05321 ar & serialization::make_nvp("index1_data", index1_data_);
05322 ar & serialization::make_nvp("index2_data", index2_data_);
05323 ar & serialization::make_nvp("value_data", value_data_);
05324 storage_invariants();
05325 }
05326
05327 private:
05328 void storage_invariants () const
05329 {
05330 BOOST_UBLAS_CHECK (capacity_ == index1_data_.size (), internal_logic ());
05331 BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ());
05332 BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
05333 BOOST_UBLAS_CHECK (filled_ <= capacity_, internal_logic ());
05334 BOOST_UBLAS_CHECK (sorted_filled_ <= filled_, internal_logic ());
05335 BOOST_UBLAS_CHECK (sorted_ == (sorted_filled_ == filled_), internal_logic ());
05336 }
05337
05338 size_type size1_;
05339 size_type size2_;
05340 array_size_type capacity_;
05341 mutable array_size_type filled_;
05342 mutable array_size_type sorted_filled_;
05343 mutable bool sorted_;
05344 mutable index_array_type index1_data_;
05345 mutable index_array_type index2_data_;
05346 mutable value_array_type value_data_;
05347 static const value_type zero_;
05348
05349 BOOST_UBLAS_INLINE
05350 static size_type zero_based (size_type k_based_index) {
05351 return k_based_index - IB;
05352 }
05353 BOOST_UBLAS_INLINE
05354 static size_type k_based (size_type zero_based_index) {
05355 return zero_based_index + IB;
05356 }
05357
05358 friend class iterator1;
05359 friend class iterator2;
05360 friend class const_iterator1;
05361 friend class const_iterator2;
05362 };
05363
05364 template<class T, class L, std::size_t IB, class IA, class TA>
05365 const typename coordinate_matrix<T, L, IB, IA, TA>::value_type coordinate_matrix<T, L, IB, IA, TA>::zero_ = value_type();
05366
05367 }}}
05368
05369 #endif