annotate DEPENDENCIES/generic/include/boost/numeric/ublas/matrix_sparse.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //
Chris@16 2 // Copyright (c) 2000-2007
Chris@16 3 // Joerg Walter, Mathias Koch, Gunter Winkler
Chris@16 4 //
Chris@16 5 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 6 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8 //
Chris@16 9 // The authors gratefully acknowledge the support of
Chris@16 10 // GeNeSys mbH & Co. KG in producing this work.
Chris@16 11 //
Chris@16 12
Chris@16 13 #ifndef _BOOST_UBLAS_MATRIX_SPARSE_
Chris@16 14 #define _BOOST_UBLAS_MATRIX_SPARSE_
Chris@16 15
Chris@16 16 #include <boost/numeric/ublas/vector_sparse.hpp>
Chris@16 17 #include <boost/numeric/ublas/matrix_expression.hpp>
Chris@16 18 #include <boost/numeric/ublas/detail/matrix_assign.hpp>
Chris@16 19 #if BOOST_UBLAS_TYPE_CHECK
Chris@16 20 #include <boost/numeric/ublas/matrix.hpp>
Chris@16 21 #endif
Chris@16 22
Chris@16 23 // Iterators based on ideas of Jeremy Siek
Chris@16 24
Chris@16 25 namespace boost { namespace numeric { namespace ublas {
Chris@16 26
Chris@16 27 #ifdef BOOST_UBLAS_STRICT_MATRIX_SPARSE
Chris@16 28
Chris@16 29 template<class M>
Chris@16 30 class sparse_matrix_element:
Chris@16 31 public container_reference<M> {
Chris@16 32 public:
Chris@16 33 typedef M matrix_type;
Chris@16 34 typedef typename M::size_type size_type;
Chris@16 35 typedef typename M::value_type value_type;
Chris@16 36 typedef const value_type &const_reference;
Chris@16 37 typedef value_type *pointer;
Chris@16 38 typedef const value_type *const_pointer;
Chris@16 39
Chris@16 40 private:
Chris@16 41 // Proxied element operations
Chris@16 42 void get_d () const {
Chris@16 43 const_pointer p = (*this) ().find_element (i_, j_);
Chris@16 44 if (p)
Chris@16 45 d_ = *p;
Chris@16 46 else
Chris@16 47 d_ = value_type/*zero*/();
Chris@16 48 }
Chris@16 49
Chris@16 50 void set (const value_type &s) const {
Chris@16 51 pointer p = (*this) ().find_element (i_, j_);
Chris@16 52 if (!p)
Chris@16 53 (*this) ().insert_element (i_, j_, s);
Chris@16 54 else
Chris@16 55 *p = s;
Chris@16 56 }
Chris@16 57
Chris@16 58 public:
Chris@16 59 // Construction and destruction
Chris@16 60 BOOST_UBLAS_INLINE
Chris@16 61 sparse_matrix_element (matrix_type &m, size_type i, size_type j):
Chris@16 62 container_reference<matrix_type> (m), i_ (i), j_ (j) {
Chris@16 63 }
Chris@16 64 BOOST_UBLAS_INLINE
Chris@16 65 sparse_matrix_element (const sparse_matrix_element &p):
Chris@16 66 container_reference<matrix_type> (p), i_ (p.i_), j_ (p.j_) {}
Chris@16 67 BOOST_UBLAS_INLINE
Chris@16 68 ~sparse_matrix_element () {
Chris@16 69 }
Chris@16 70
Chris@16 71 // Assignment
Chris@16 72 BOOST_UBLAS_INLINE
Chris@16 73 sparse_matrix_element &operator = (const sparse_matrix_element &p) {
Chris@16 74 // Overide the implict copy assignment
Chris@16 75 p.get_d ();
Chris@16 76 set (p.d_);
Chris@16 77 return *this;
Chris@16 78 }
Chris@16 79 template<class D>
Chris@16 80 BOOST_UBLAS_INLINE
Chris@16 81 sparse_matrix_element &operator = (const D &d) {
Chris@16 82 set (d);
Chris@16 83 return *this;
Chris@16 84 }
Chris@16 85 template<class D>
Chris@16 86 BOOST_UBLAS_INLINE
Chris@16 87 sparse_matrix_element &operator += (const D &d) {
Chris@16 88 get_d ();
Chris@16 89 d_ += d;
Chris@16 90 set (d_);
Chris@16 91 return *this;
Chris@16 92 }
Chris@16 93 template<class D>
Chris@16 94 BOOST_UBLAS_INLINE
Chris@16 95 sparse_matrix_element &operator -= (const D &d) {
Chris@16 96 get_d ();
Chris@16 97 d_ -= d;
Chris@16 98 set (d_);
Chris@16 99 return *this;
Chris@16 100 }
Chris@16 101 template<class D>
Chris@16 102 BOOST_UBLAS_INLINE
Chris@16 103 sparse_matrix_element &operator *= (const D &d) {
Chris@16 104 get_d ();
Chris@16 105 d_ *= d;
Chris@16 106 set (d_);
Chris@16 107 return *this;
Chris@16 108 }
Chris@16 109 template<class D>
Chris@16 110 BOOST_UBLAS_INLINE
Chris@16 111 sparse_matrix_element &operator /= (const D &d) {
Chris@16 112 get_d ();
Chris@16 113 d_ /= d;
Chris@16 114 set (d_);
Chris@16 115 return *this;
Chris@16 116 }
Chris@16 117
Chris@16 118 // Comparison
Chris@16 119 template<class D>
Chris@16 120 BOOST_UBLAS_INLINE
Chris@16 121 bool operator == (const D &d) const {
Chris@16 122 get_d ();
Chris@16 123 return d_ == d;
Chris@16 124 }
Chris@16 125 template<class D>
Chris@16 126 BOOST_UBLAS_INLINE
Chris@16 127 bool operator != (const D &d) const {
Chris@16 128 get_d ();
Chris@16 129 return d_ != d;
Chris@16 130 }
Chris@16 131
Chris@16 132 // Conversion - weak link in proxy as d_ is not a perfect alias for the element
Chris@16 133 BOOST_UBLAS_INLINE
Chris@16 134 operator const_reference () const {
Chris@16 135 get_d ();
Chris@16 136 return d_;
Chris@16 137 }
Chris@16 138
Chris@16 139 // Conversion to reference - may be invalidated
Chris@16 140 BOOST_UBLAS_INLINE
Chris@16 141 value_type& ref () const {
Chris@16 142 const pointer p = (*this) ().find_element (i_, j_);
Chris@16 143 if (!p)
Chris@16 144 return (*this) ().insert_element (i_, j_, value_type/*zero*/());
Chris@16 145 else
Chris@16 146 return *p;
Chris@16 147 }
Chris@16 148
Chris@16 149 private:
Chris@16 150 size_type i_;
Chris@16 151 size_type j_;
Chris@16 152 mutable value_type d_;
Chris@16 153 };
Chris@16 154
Chris@16 155 /*
Chris@16 156 * Generalise explicit reference access
Chris@16 157 */
Chris@16 158 namespace detail {
Chris@16 159 template <class V>
Chris@16 160 struct element_reference<sparse_matrix_element<V> > {
Chris@16 161 typedef typename V::value_type& reference;
Chris@16 162 static reference get_reference (const sparse_matrix_element<V>& sve)
Chris@16 163 {
Chris@16 164 return sve.ref ();
Chris@16 165 }
Chris@16 166 };
Chris@16 167 }
Chris@16 168
Chris@16 169
Chris@16 170 template<class M>
Chris@16 171 struct type_traits<sparse_matrix_element<M> > {
Chris@16 172 typedef typename M::value_type element_type;
Chris@16 173 typedef type_traits<sparse_matrix_element<M> > self_type;
Chris@16 174 typedef typename type_traits<element_type>::value_type value_type;
Chris@16 175 typedef typename type_traits<element_type>::const_reference const_reference;
Chris@16 176 typedef sparse_matrix_element<M> reference;
Chris@16 177 typedef typename type_traits<element_type>::real_type real_type;
Chris@16 178 typedef typename type_traits<element_type>::precision_type precision_type;
Chris@16 179
Chris@16 180 static const unsigned plus_complexity = type_traits<element_type>::plus_complexity;
Chris@16 181 static const unsigned multiplies_complexity = type_traits<element_type>::multiplies_complexity;
Chris@16 182
Chris@16 183 static
Chris@16 184 BOOST_UBLAS_INLINE
Chris@16 185 real_type real (const_reference t) {
Chris@16 186 return type_traits<element_type>::real (t);
Chris@16 187 }
Chris@16 188 static
Chris@16 189 BOOST_UBLAS_INLINE
Chris@16 190 real_type imag (const_reference t) {
Chris@16 191 return type_traits<element_type>::imag (t);
Chris@16 192 }
Chris@16 193 static
Chris@16 194 BOOST_UBLAS_INLINE
Chris@16 195 value_type conj (const_reference t) {
Chris@16 196 return type_traits<element_type>::conj (t);
Chris@16 197 }
Chris@16 198
Chris@16 199 static
Chris@16 200 BOOST_UBLAS_INLINE
Chris@16 201 real_type type_abs (const_reference t) {
Chris@16 202 return type_traits<element_type>::type_abs (t);
Chris@16 203 }
Chris@16 204 static
Chris@16 205 BOOST_UBLAS_INLINE
Chris@16 206 value_type type_sqrt (const_reference t) {
Chris@16 207 return type_traits<element_type>::type_sqrt (t);
Chris@16 208 }
Chris@16 209
Chris@16 210 static
Chris@16 211 BOOST_UBLAS_INLINE
Chris@16 212 real_type norm_1 (const_reference t) {
Chris@16 213 return type_traits<element_type>::norm_1 (t);
Chris@16 214 }
Chris@16 215 static
Chris@16 216 BOOST_UBLAS_INLINE
Chris@16 217 real_type norm_2 (const_reference t) {
Chris@16 218 return type_traits<element_type>::norm_2 (t);
Chris@16 219 }
Chris@16 220 static
Chris@16 221 BOOST_UBLAS_INLINE
Chris@16 222 real_type norm_inf (const_reference t) {
Chris@16 223 return type_traits<element_type>::norm_inf (t);
Chris@16 224 }
Chris@16 225
Chris@16 226 static
Chris@16 227 BOOST_UBLAS_INLINE
Chris@16 228 bool equals (const_reference t1, const_reference t2) {
Chris@16 229 return type_traits<element_type>::equals (t1, t2);
Chris@16 230 }
Chris@16 231 };
Chris@16 232
Chris@16 233 template<class M1, class T2>
Chris@16 234 struct promote_traits<sparse_matrix_element<M1>, T2> {
Chris@16 235 typedef typename promote_traits<typename sparse_matrix_element<M1>::value_type, T2>::promote_type promote_type;
Chris@16 236 };
Chris@16 237 template<class T1, class M2>
Chris@16 238 struct promote_traits<T1, sparse_matrix_element<M2> > {
Chris@16 239 typedef typename promote_traits<T1, typename sparse_matrix_element<M2>::value_type>::promote_type promote_type;
Chris@16 240 };
Chris@16 241 template<class M1, class M2>
Chris@16 242 struct promote_traits<sparse_matrix_element<M1>, sparse_matrix_element<M2> > {
Chris@16 243 typedef typename promote_traits<typename sparse_matrix_element<M1>::value_type,
Chris@16 244 typename sparse_matrix_element<M2>::value_type>::promote_type promote_type;
Chris@16 245 };
Chris@16 246
Chris@16 247 #endif
Chris@16 248
Chris@16 249 /** \brief Index map based sparse matrix of values of type \c T
Chris@16 250 *
Chris@16 251 * This class represents a matrix by using a \c key to value mapping. The default type is
Chris@16 252 * \code template<class T, class L = row_major, class A = map_std<std::size_t, T> > class mapped_matrix; \endcode
Chris@16 253 * So, by default a STL map container is used to associate keys and values. The key is computed depending on
Chris@16 254 * the layout type \c L as \code key = layout_type::element(i, size1_, j, size2_); \endcode
Chris@16 255 * which means \code key = (i*size2+j) \endcode for a row major matrix.
Chris@16 256 * Limitations: The matrix size must not exceed \f$(size1*size2) < \f$ \code std::limits<std::size_t> \endcode.
Chris@16 257 * The \ref find1() and \ref find2() operations have a complexity of at least \f$\mathcal{O}(log(nnz))\f$, depending
Chris@16 258 * on the efficiency of \c std::lower_bound on the key set of the map.
Chris@16 259 * Orientation and storage can also be specified, otherwise a row major orientation is used.
Chris@16 260 * It is \b not required by the storage to initialize elements of the matrix. By default, the orientation is \c row_major.
Chris@16 261 *
Chris@16 262 * \sa fwd.hpp, storage_sparse.hpp
Chris@16 263 *
Chris@16 264 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
Chris@16 265 * \tparam L the storage organization. It can be either \c row_major or \c column_major. By default it is \c row_major
Chris@16 266 */
Chris@16 267 template<class T, class L, class A>
Chris@16 268 class mapped_matrix:
Chris@16 269 public matrix_container<mapped_matrix<T, L, A> > {
Chris@16 270
Chris@16 271 typedef T &true_reference;
Chris@16 272 typedef T *pointer;
Chris@16 273 typedef const T * const_pointer;
Chris@16 274 typedef L layout_type;
Chris@16 275 typedef mapped_matrix<T, L, A> self_type;
Chris@16 276 public:
Chris@16 277 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
Chris@16 278 using matrix_container<self_type>::operator ();
Chris@16 279 #endif
Chris@16 280 typedef typename A::size_type size_type;
Chris@16 281 typedef typename A::difference_type difference_type;
Chris@16 282 typedef T value_type;
Chris@16 283 typedef A array_type;
Chris@16 284 typedef const T &const_reference;
Chris@16 285 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
Chris@16 286 typedef typename detail::map_traits<A, T>::reference reference;
Chris@16 287 #else
Chris@16 288 typedef sparse_matrix_element<self_type> reference;
Chris@16 289 #endif
Chris@16 290 typedef const matrix_reference<const self_type> const_closure_type;
Chris@16 291 typedef matrix_reference<self_type> closure_type;
Chris@16 292 typedef mapped_vector<T, A> vector_temporary_type;
Chris@16 293 typedef self_type matrix_temporary_type;
Chris@16 294 typedef sparse_tag storage_category;
Chris@16 295 typedef typename L::orientation_category orientation_category;
Chris@16 296
Chris@16 297 // Construction and destruction
Chris@16 298 BOOST_UBLAS_INLINE
Chris@16 299 mapped_matrix ():
Chris@16 300 matrix_container<self_type> (),
Chris@16 301 size1_ (0), size2_ (0), data_ () {}
Chris@16 302 BOOST_UBLAS_INLINE
Chris@16 303 mapped_matrix (size_type size1, size_type size2, size_type non_zeros = 0):
Chris@16 304 matrix_container<self_type> (),
Chris@16 305 size1_ (size1), size2_ (size2), data_ () {
Chris@16 306 detail::map_reserve (data (), restrict_capacity (non_zeros));
Chris@16 307 }
Chris@16 308 BOOST_UBLAS_INLINE
Chris@16 309 mapped_matrix (const mapped_matrix &m):
Chris@16 310 matrix_container<self_type> (),
Chris@16 311 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
Chris@16 312 template<class AE>
Chris@16 313 BOOST_UBLAS_INLINE
Chris@16 314 mapped_matrix (const matrix_expression<AE> &ae, size_type non_zeros = 0):
Chris@16 315 matrix_container<self_type> (),
Chris@16 316 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () {
Chris@16 317 detail::map_reserve (data (), restrict_capacity (non_zeros));
Chris@16 318 matrix_assign<scalar_assign> (*this, ae);
Chris@16 319 }
Chris@16 320
Chris@16 321 // Accessors
Chris@16 322 BOOST_UBLAS_INLINE
Chris@16 323 size_type size1 () const {
Chris@16 324 return size1_;
Chris@16 325 }
Chris@16 326 BOOST_UBLAS_INLINE
Chris@16 327 size_type size2 () const {
Chris@16 328 return size2_;
Chris@16 329 }
Chris@16 330 BOOST_UBLAS_INLINE
Chris@16 331 size_type nnz_capacity () const {
Chris@16 332 return detail::map_capacity (data ());
Chris@16 333 }
Chris@16 334 BOOST_UBLAS_INLINE
Chris@16 335 size_type nnz () const {
Chris@16 336 return data (). size ();
Chris@16 337 }
Chris@16 338
Chris@16 339 // Storage accessors
Chris@16 340 BOOST_UBLAS_INLINE
Chris@16 341 const array_type &data () const {
Chris@16 342 return data_;
Chris@16 343 }
Chris@16 344 BOOST_UBLAS_INLINE
Chris@16 345 array_type &data () {
Chris@16 346 return data_;
Chris@16 347 }
Chris@16 348
Chris@16 349 // Resizing
Chris@16 350 private:
Chris@16 351 BOOST_UBLAS_INLINE
Chris@16 352 size_type restrict_capacity (size_type non_zeros) const {
Chris@16 353 // Guarding against overflow - thanks to Alexei Novakov for the hint.
Chris@16 354 // non_zeros = (std::min) (non_zeros, size1_ * size2_);
Chris@16 355 if (size1_ > 0 && non_zeros / size1_ >= size2_)
Chris@16 356 non_zeros = size1_ * size2_;
Chris@16 357 return non_zeros;
Chris@16 358 }
Chris@16 359 public:
Chris@16 360 BOOST_UBLAS_INLINE
Chris@16 361 void resize (size_type size1, size_type size2, bool preserve = true) {
Chris@16 362 // FIXME preserve unimplemented
Chris@16 363 BOOST_UBLAS_CHECK (!preserve, internal_logic ());
Chris@16 364 size1_ = size1;
Chris@16 365 size2_ = size2;
Chris@16 366 data ().clear ();
Chris@16 367 }
Chris@16 368
Chris@16 369 // Reserving
Chris@16 370 BOOST_UBLAS_INLINE
Chris@16 371 void reserve (size_type non_zeros, bool preserve = true) {
Chris@16 372 detail::map_reserve (data (), restrict_capacity (non_zeros));
Chris@16 373 }
Chris@16 374
Chris@16 375 // Element support
Chris@16 376 BOOST_UBLAS_INLINE
Chris@16 377 pointer find_element (size_type i, size_type j) {
Chris@16 378 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
Chris@16 379 }
Chris@16 380 BOOST_UBLAS_INLINE
Chris@16 381 const_pointer find_element (size_type i, size_type j) const {
Chris@16 382 const size_type element = layout_type::element (i, size1_, j, size2_);
Chris@16 383 const_subiterator_type it (data ().find (element));
Chris@16 384 if (it == data ().end ())
Chris@16 385 return 0;
Chris@16 386 BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map
Chris@16 387 return &(*it).second;
Chris@16 388 }
Chris@16 389
Chris@16 390 // Element access
Chris@16 391 BOOST_UBLAS_INLINE
Chris@16 392 const_reference operator () (size_type i, size_type j) const {
Chris@16 393 const size_type element = layout_type::element (i, size1_, j, size2_);
Chris@16 394 const_subiterator_type it (data ().find (element));
Chris@16 395 if (it == data ().end ())
Chris@16 396 return zero_;
Chris@16 397 BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map
Chris@16 398 return (*it).second;
Chris@16 399 }
Chris@16 400 BOOST_UBLAS_INLINE
Chris@16 401 reference operator () (size_type i, size_type j) {
Chris@16 402 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
Chris@16 403 const size_type element = layout_type::element (i, size1_, j, size2_);
Chris@16 404 std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (element, value_type/*zero*/())));
Chris@16 405 BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ()); // broken map
Chris@16 406 return (ii.first)->second;
Chris@16 407 #else
Chris@16 408 return reference (*this, i, j);
Chris@16 409 #endif
Chris@16 410 }
Chris@16 411
Chris@16 412 // Element assingment
Chris@16 413 BOOST_UBLAS_INLINE
Chris@16 414 true_reference insert_element (size_type i, size_type j, const_reference t) {
Chris@16 415 BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
Chris@16 416 const size_type element = layout_type::element (i, size1_, j, size2_);
Chris@16 417 std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (element, t)));
Chris@16 418 BOOST_UBLAS_CHECK ((ii.first)->first == element, internal_logic ()); // broken map
Chris@16 419 if (!ii.second) // existing element
Chris@16 420 (ii.first)->second = t;
Chris@16 421 return (ii.first)->second;
Chris@16 422 }
Chris@16 423 BOOST_UBLAS_INLINE
Chris@16 424 void erase_element (size_type i, size_type j) {
Chris@16 425 subiterator_type it = data ().find (layout_type::element (i, size1_, j, size2_));
Chris@16 426 if (it == data ().end ())
Chris@16 427 return;
Chris@16 428 data ().erase (it);
Chris@16 429 }
Chris@16 430
Chris@16 431 // Zeroing
Chris@16 432 BOOST_UBLAS_INLINE
Chris@16 433 void clear () {
Chris@16 434 data ().clear ();
Chris@16 435 }
Chris@16 436
Chris@16 437 // Assignment
Chris@16 438 BOOST_UBLAS_INLINE
Chris@16 439 mapped_matrix &operator = (const mapped_matrix &m) {
Chris@16 440 if (this != &m) {
Chris@16 441 size1_ = m.size1_;
Chris@16 442 size2_ = m.size2_;
Chris@16 443 data () = m.data ();
Chris@16 444 }
Chris@16 445 return *this;
Chris@16 446 }
Chris@16 447 template<class C> // Container assignment without temporary
Chris@16 448 BOOST_UBLAS_INLINE
Chris@16 449 mapped_matrix &operator = (const matrix_container<C> &m) {
Chris@16 450 resize (m ().size1 (), m ().size2 (), false);
Chris@16 451 assign (m);
Chris@16 452 return *this;
Chris@16 453 }
Chris@16 454 BOOST_UBLAS_INLINE
Chris@16 455 mapped_matrix &assign_temporary (mapped_matrix &m) {
Chris@16 456 swap (m);
Chris@16 457 return *this;
Chris@16 458 }
Chris@16 459 template<class AE>
Chris@16 460 BOOST_UBLAS_INLINE
Chris@16 461 mapped_matrix &operator = (const matrix_expression<AE> &ae) {
Chris@16 462 self_type temporary (ae, detail::map_capacity (data ()));
Chris@16 463 return assign_temporary (temporary);
Chris@16 464 }
Chris@16 465 template<class AE>
Chris@16 466 BOOST_UBLAS_INLINE
Chris@16 467 mapped_matrix &assign (const matrix_expression<AE> &ae) {
Chris@16 468 matrix_assign<scalar_assign> (*this, ae);
Chris@16 469 return *this;
Chris@16 470 }
Chris@16 471 template<class AE>
Chris@16 472 BOOST_UBLAS_INLINE
Chris@16 473 mapped_matrix& operator += (const matrix_expression<AE> &ae) {
Chris@16 474 self_type temporary (*this + ae, detail::map_capacity (data ()));
Chris@16 475 return assign_temporary (temporary);
Chris@16 476 }
Chris@16 477 template<class C> // Container assignment without temporary
Chris@16 478 BOOST_UBLAS_INLINE
Chris@16 479 mapped_matrix &operator += (const matrix_container<C> &m) {
Chris@16 480 plus_assign (m);
Chris@16 481 return *this;
Chris@16 482 }
Chris@16 483 template<class AE>
Chris@16 484 BOOST_UBLAS_INLINE
Chris@16 485 mapped_matrix &plus_assign (const matrix_expression<AE> &ae) {
Chris@16 486 matrix_assign<scalar_plus_assign> (*this, ae);
Chris@16 487 return *this;
Chris@16 488 }
Chris@16 489 template<class AE>
Chris@16 490 BOOST_UBLAS_INLINE
Chris@16 491 mapped_matrix& operator -= (const matrix_expression<AE> &ae) {
Chris@16 492 self_type temporary (*this - ae, detail::map_capacity (data ()));
Chris@16 493 return assign_temporary (temporary);
Chris@16 494 }
Chris@16 495 template<class C> // Container assignment without temporary
Chris@16 496 BOOST_UBLAS_INLINE
Chris@16 497 mapped_matrix &operator -= (const matrix_container<C> &m) {
Chris@16 498 minus_assign (m);
Chris@16 499 return *this;
Chris@16 500 }
Chris@16 501 template<class AE>
Chris@16 502 BOOST_UBLAS_INLINE
Chris@16 503 mapped_matrix &minus_assign (const matrix_expression<AE> &ae) {
Chris@16 504 matrix_assign<scalar_minus_assign> (*this, ae);
Chris@16 505 return *this;
Chris@16 506 }
Chris@16 507 template<class AT>
Chris@16 508 BOOST_UBLAS_INLINE
Chris@16 509 mapped_matrix& operator *= (const AT &at) {
Chris@16 510 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
Chris@16 511 return *this;
Chris@16 512 }
Chris@16 513 template<class AT>
Chris@16 514 BOOST_UBLAS_INLINE
Chris@16 515 mapped_matrix& operator /= (const AT &at) {
Chris@16 516 matrix_assign_scalar<scalar_divides_assign> (*this, at);
Chris@16 517 return *this;
Chris@16 518 }
Chris@16 519
Chris@16 520 // Swapping
Chris@16 521 BOOST_UBLAS_INLINE
Chris@16 522 void swap (mapped_matrix &m) {
Chris@16 523 if (this != &m) {
Chris@16 524 std::swap (size1_, m.size1_);
Chris@16 525 std::swap (size2_, m.size2_);
Chris@16 526 data ().swap (m.data ());
Chris@16 527 }
Chris@16 528 }
Chris@16 529 BOOST_UBLAS_INLINE
Chris@16 530 friend void swap (mapped_matrix &m1, mapped_matrix &m2) {
Chris@16 531 m1.swap (m2);
Chris@16 532 }
Chris@16 533
Chris@16 534 // Iterator types
Chris@16 535 private:
Chris@16 536 // Use storage iterator
Chris@16 537 typedef typename A::const_iterator const_subiterator_type;
Chris@16 538 typedef typename A::iterator subiterator_type;
Chris@16 539
Chris@16 540 BOOST_UBLAS_INLINE
Chris@16 541 true_reference at_element (size_type i, size_type j) {
Chris@16 542 const size_type element = layout_type::element (i, size1_, j, size2_);
Chris@16 543 subiterator_type it (data ().find (element));
Chris@16 544 BOOST_UBLAS_CHECK (it != data ().end(), bad_index ());
Chris@16 545 BOOST_UBLAS_CHECK ((*it).first == element, internal_logic ()); // broken map
Chris@16 546 return it->second;
Chris@16 547 }
Chris@16 548
Chris@16 549 public:
Chris@16 550 class const_iterator1;
Chris@16 551 class iterator1;
Chris@16 552 class const_iterator2;
Chris@16 553 class iterator2;
Chris@16 554 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
Chris@16 555 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
Chris@16 556 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
Chris@16 557 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
Chris@16 558
Chris@16 559 // Element lookup
Chris@16 560 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 561 const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
Chris@16 562 const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
Chris@16 563 const_subiterator_type it_end (data ().end ());
Chris@16 564 size_type index1 = size_type (-1);
Chris@16 565 size_type index2 = size_type (-1);
Chris@16 566 while (rank == 1 && it != it_end) {
Chris@16 567 index1 = layout_type::index_i ((*it).first, size1_, size2_);
Chris@16 568 index2 = layout_type::index_j ((*it).first, size1_, size2_);
Chris@16 569 if (direction > 0) {
Chris@16 570 if ((index1 >= i && index2 == j) || (i >= size1_))
Chris@16 571 break;
Chris@16 572 ++ i;
Chris@16 573 } else /* if (direction < 0) */ {
Chris@16 574 if ((index1 <= i && index2 == j) || (i == 0))
Chris@16 575 break;
Chris@16 576 -- i;
Chris@16 577 }
Chris@16 578 it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
Chris@16 579 }
Chris@16 580 if (rank == 1 && index2 != j) {
Chris@16 581 if (direction > 0)
Chris@16 582 i = size1_;
Chris@16 583 else /* if (direction < 0) */
Chris@16 584 i = 0;
Chris@16 585 rank = 0;
Chris@16 586 }
Chris@16 587 return const_iterator1 (*this, rank, i, j, it);
Chris@16 588 }
Chris@16 589 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 590 iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
Chris@16 591 subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
Chris@16 592 subiterator_type it_end (data ().end ());
Chris@16 593 size_type index1 = size_type (-1);
Chris@16 594 size_type index2 = size_type (-1);
Chris@16 595 while (rank == 1 && it != it_end) {
Chris@16 596 index1 = layout_type::index_i ((*it).first, size1_, size2_);
Chris@16 597 index2 = layout_type::index_j ((*it).first, size1_, size2_);
Chris@16 598 if (direction > 0) {
Chris@16 599 if ((index1 >= i && index2 == j) || (i >= size1_))
Chris@16 600 break;
Chris@16 601 ++ i;
Chris@16 602 } else /* if (direction < 0) */ {
Chris@16 603 if ((index1 <= i && index2 == j) || (i == 0))
Chris@16 604 break;
Chris@16 605 -- i;
Chris@16 606 }
Chris@16 607 it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
Chris@16 608 }
Chris@16 609 if (rank == 1 && index2 != j) {
Chris@16 610 if (direction > 0)
Chris@16 611 i = size1_;
Chris@16 612 else /* if (direction < 0) */
Chris@16 613 i = 0;
Chris@16 614 rank = 0;
Chris@16 615 }
Chris@16 616 return iterator1 (*this, rank, i, j, it);
Chris@16 617 }
Chris@16 618 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 619 const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
Chris@16 620 const_subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
Chris@16 621 const_subiterator_type it_end (data ().end ());
Chris@16 622 size_type index1 = size_type (-1);
Chris@16 623 size_type index2 = size_type (-1);
Chris@16 624 while (rank == 1 && it != it_end) {
Chris@16 625 index1 = layout_type::index_i ((*it).first, size1_, size2_);
Chris@16 626 index2 = layout_type::index_j ((*it).first, size1_, size2_);
Chris@16 627 if (direction > 0) {
Chris@16 628 if ((index2 >= j && index1 == i) || (j >= size2_))
Chris@16 629 break;
Chris@16 630 ++ j;
Chris@16 631 } else /* if (direction < 0) */ {
Chris@16 632 if ((index2 <= j && index1 == i) || (j == 0))
Chris@16 633 break;
Chris@16 634 -- j;
Chris@16 635 }
Chris@16 636 it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
Chris@16 637 }
Chris@16 638 if (rank == 1 && index1 != i) {
Chris@16 639 if (direction > 0)
Chris@16 640 j = size2_;
Chris@16 641 else /* if (direction < 0) */
Chris@16 642 j = 0;
Chris@16 643 rank = 0;
Chris@16 644 }
Chris@16 645 return const_iterator2 (*this, rank, i, j, it);
Chris@16 646 }
Chris@16 647 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 648 iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
Chris@16 649 subiterator_type it (data ().lower_bound (layout_type::address (i, size1_, j, size2_)));
Chris@16 650 subiterator_type it_end (data ().end ());
Chris@16 651 size_type index1 = size_type (-1);
Chris@16 652 size_type index2 = size_type (-1);
Chris@16 653 while (rank == 1 && it != it_end) {
Chris@16 654 index1 = layout_type::index_i ((*it).first, size1_, size2_);
Chris@16 655 index2 = layout_type::index_j ((*it).first, size1_, size2_);
Chris@16 656 if (direction > 0) {
Chris@16 657 if ((index2 >= j && index1 == i) || (j >= size2_))
Chris@16 658 break;
Chris@16 659 ++ j;
Chris@16 660 } else /* if (direction < 0) */ {
Chris@16 661 if ((index2 <= j && index1 == i) || (j == 0))
Chris@16 662 break;
Chris@16 663 -- j;
Chris@16 664 }
Chris@16 665 it = data ().lower_bound (layout_type::address (i, size1_, j, size2_));
Chris@16 666 }
Chris@16 667 if (rank == 1 && index1 != i) {
Chris@16 668 if (direction > 0)
Chris@16 669 j = size2_;
Chris@16 670 else /* if (direction < 0) */
Chris@16 671 j = 0;
Chris@16 672 rank = 0;
Chris@16 673 }
Chris@16 674 return iterator2 (*this, rank, i, j, it);
Chris@16 675 }
Chris@16 676
Chris@16 677
Chris@16 678 class const_iterator1:
Chris@16 679 public container_const_reference<mapped_matrix>,
Chris@16 680 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 681 const_iterator1, value_type> {
Chris@16 682 public:
Chris@16 683 typedef typename mapped_matrix::value_type value_type;
Chris@16 684 typedef typename mapped_matrix::difference_type difference_type;
Chris@16 685 typedef typename mapped_matrix::const_reference reference;
Chris@16 686 typedef const typename mapped_matrix::pointer pointer;
Chris@16 687
Chris@16 688 typedef const_iterator2 dual_iterator_type;
Chris@16 689 typedef const_reverse_iterator2 dual_reverse_iterator_type;
Chris@16 690
Chris@16 691 // Construction and destruction
Chris@16 692 BOOST_UBLAS_INLINE
Chris@16 693 const_iterator1 ():
Chris@16 694 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
Chris@16 695 BOOST_UBLAS_INLINE
Chris@16 696 const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_subiterator_type &it):
Chris@16 697 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
Chris@16 698 BOOST_UBLAS_INLINE
Chris@16 699 const_iterator1 (const iterator1 &it):
Chris@16 700 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
Chris@16 701
Chris@16 702 // Arithmetic
Chris@16 703 BOOST_UBLAS_INLINE
Chris@16 704 const_iterator1 &operator ++ () {
Chris@16 705 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 706 ++ it_;
Chris@16 707 else
Chris@16 708 *this = (*this) ().find1 (rank_, index1 () + 1, j_, 1);
Chris@16 709 return *this;
Chris@16 710 }
Chris@16 711 BOOST_UBLAS_INLINE
Chris@16 712 const_iterator1 &operator -- () {
Chris@16 713 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 714 -- it_;
Chris@16 715 else
Chris@16 716 *this = (*this) ().find1 (rank_, index1 () - 1, j_, -1);
Chris@16 717 return *this;
Chris@16 718 }
Chris@16 719
Chris@16 720 // Dereference
Chris@16 721 BOOST_UBLAS_INLINE
Chris@16 722 const_reference operator * () const {
Chris@16 723 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 724 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 725 if (rank_ == 1) {
Chris@16 726 return (*it_).second;
Chris@16 727 } else {
Chris@16 728 return (*this) () (i_, j_);
Chris@16 729 }
Chris@16 730 }
Chris@16 731
Chris@16 732 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 733 BOOST_UBLAS_INLINE
Chris@16 734 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 735 typename self_type::
Chris@16 736 #endif
Chris@16 737 const_iterator2 begin () const {
Chris@16 738 const self_type &m = (*this) ();
Chris@16 739 return m.find2 (1, index1 (), 0);
Chris@16 740 }
Chris@16 741 BOOST_UBLAS_INLINE
Chris@16 742 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 743 typename self_type::
Chris@16 744 #endif
Chris@101 745 const_iterator2 cbegin () const {
Chris@101 746 return begin ();
Chris@101 747 }
Chris@101 748 BOOST_UBLAS_INLINE
Chris@101 749 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 750 typename self_type::
Chris@101 751 #endif
Chris@16 752 const_iterator2 end () const {
Chris@16 753 const self_type &m = (*this) ();
Chris@16 754 return m.find2 (1, index1 (), m.size2 ());
Chris@16 755 }
Chris@16 756 BOOST_UBLAS_INLINE
Chris@16 757 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 758 typename self_type::
Chris@16 759 #endif
Chris@101 760 const_iterator2 cend () const {
Chris@101 761 return end ();
Chris@101 762 }
Chris@101 763 BOOST_UBLAS_INLINE
Chris@101 764 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 765 typename self_type::
Chris@101 766 #endif
Chris@16 767 const_reverse_iterator2 rbegin () const {
Chris@16 768 return const_reverse_iterator2 (end ());
Chris@16 769 }
Chris@16 770 BOOST_UBLAS_INLINE
Chris@16 771 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 772 typename self_type::
Chris@16 773 #endif
Chris@101 774 const_reverse_iterator2 crbegin () const {
Chris@101 775 return rbegin ();
Chris@101 776 }
Chris@101 777 BOOST_UBLAS_INLINE
Chris@101 778 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 779 typename self_type::
Chris@101 780 #endif
Chris@16 781 const_reverse_iterator2 rend () const {
Chris@16 782 return const_reverse_iterator2 (begin ());
Chris@16 783 }
Chris@101 784 BOOST_UBLAS_INLINE
Chris@101 785 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 786 typename self_type::
Chris@101 787 #endif
Chris@101 788 const_reverse_iterator2 crend () const {
Chris@101 789 return rend ();
Chris@101 790 }
Chris@16 791 #endif
Chris@16 792
Chris@16 793 // Indices
Chris@16 794 BOOST_UBLAS_INLINE
Chris@16 795 size_type index1 () const {
Chris@16 796 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
Chris@16 797 if (rank_ == 1) {
Chris@16 798 const self_type &m = (*this) ();
Chris@16 799 BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
Chris@16 800 return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
Chris@16 801 } else {
Chris@16 802 return i_;
Chris@16 803 }
Chris@16 804 }
Chris@16 805 BOOST_UBLAS_INLINE
Chris@16 806 size_type index2 () const {
Chris@16 807 if (rank_ == 1) {
Chris@16 808 const self_type &m = (*this) ();
Chris@16 809 BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
Chris@16 810 return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
Chris@16 811 } else {
Chris@16 812 return j_;
Chris@16 813 }
Chris@16 814 }
Chris@16 815
Chris@16 816 // Assignment
Chris@16 817 BOOST_UBLAS_INLINE
Chris@16 818 const_iterator1 &operator = (const const_iterator1 &it) {
Chris@16 819 container_const_reference<self_type>::assign (&it ());
Chris@16 820 rank_ = it.rank_;
Chris@16 821 i_ = it.i_;
Chris@16 822 j_ = it.j_;
Chris@16 823 it_ = it.it_;
Chris@16 824 return *this;
Chris@16 825 }
Chris@16 826
Chris@16 827 // Comparison
Chris@16 828 BOOST_UBLAS_INLINE
Chris@16 829 bool operator == (const const_iterator1 &it) const {
Chris@16 830 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 831 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 832 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 833 return it_ == it.it_;
Chris@16 834 } else {
Chris@16 835 return i_ == it.i_ && j_ == it.j_;
Chris@16 836 }
Chris@16 837 }
Chris@16 838
Chris@16 839 private:
Chris@16 840 int rank_;
Chris@16 841 size_type i_;
Chris@16 842 size_type j_;
Chris@16 843 const_subiterator_type it_;
Chris@16 844 };
Chris@16 845
Chris@16 846 BOOST_UBLAS_INLINE
Chris@16 847 const_iterator1 begin1 () const {
Chris@16 848 return find1 (0, 0, 0);
Chris@16 849 }
Chris@16 850 BOOST_UBLAS_INLINE
Chris@101 851 const_iterator1 cbegin1 () const {
Chris@101 852 return begin1 ();
Chris@101 853 }
Chris@101 854 BOOST_UBLAS_INLINE
Chris@16 855 const_iterator1 end1 () const {
Chris@16 856 return find1 (0, size1_, 0);
Chris@16 857 }
Chris@101 858 BOOST_UBLAS_INLINE
Chris@101 859 const_iterator1 cend1 () const {
Chris@101 860 return end1 ();
Chris@101 861 }
Chris@16 862
Chris@16 863 class iterator1:
Chris@16 864 public container_reference<mapped_matrix>,
Chris@16 865 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 866 iterator1, value_type> {
Chris@16 867 public:
Chris@16 868 typedef typename mapped_matrix::value_type value_type;
Chris@16 869 typedef typename mapped_matrix::difference_type difference_type;
Chris@16 870 typedef typename mapped_matrix::true_reference reference;
Chris@16 871 typedef typename mapped_matrix::pointer pointer;
Chris@16 872
Chris@16 873 typedef iterator2 dual_iterator_type;
Chris@16 874 typedef reverse_iterator2 dual_reverse_iterator_type;
Chris@16 875
Chris@16 876 // Construction and destruction
Chris@16 877 BOOST_UBLAS_INLINE
Chris@16 878 iterator1 ():
Chris@16 879 container_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
Chris@16 880 BOOST_UBLAS_INLINE
Chris@16 881 iterator1 (self_type &m, int rank, size_type i, size_type j, const subiterator_type &it):
Chris@16 882 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
Chris@16 883
Chris@16 884 // Arithmetic
Chris@16 885 BOOST_UBLAS_INLINE
Chris@16 886 iterator1 &operator ++ () {
Chris@16 887 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 888 ++ it_;
Chris@16 889 else
Chris@16 890 *this = (*this) ().find1 (rank_, index1 () + 1, j_, 1);
Chris@16 891 return *this;
Chris@16 892 }
Chris@16 893 BOOST_UBLAS_INLINE
Chris@16 894 iterator1 &operator -- () {
Chris@16 895 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 896 -- it_;
Chris@16 897 else
Chris@16 898 *this = (*this) ().find1 (rank_, index1 () - 1, j_, -1);
Chris@16 899 return *this;
Chris@16 900 }
Chris@16 901
Chris@16 902 // Dereference
Chris@16 903 BOOST_UBLAS_INLINE
Chris@16 904 reference operator * () const {
Chris@16 905 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 906 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 907 if (rank_ == 1) {
Chris@16 908 return (*it_).second;
Chris@16 909 } else {
Chris@16 910 return (*this) ().at_element (i_, j_);
Chris@16 911 }
Chris@16 912 }
Chris@16 913
Chris@16 914 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 915 BOOST_UBLAS_INLINE
Chris@16 916 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 917 typename self_type::
Chris@16 918 #endif
Chris@16 919 iterator2 begin () const {
Chris@16 920 self_type &m = (*this) ();
Chris@16 921 return m.find2 (1, index1 (), 0);
Chris@16 922 }
Chris@16 923 BOOST_UBLAS_INLINE
Chris@16 924 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 925 typename self_type::
Chris@16 926 #endif
Chris@16 927 iterator2 end () const {
Chris@16 928 self_type &m = (*this) ();
Chris@16 929 return m.find2 (1, index1 (), m.size2 ());
Chris@16 930 }
Chris@16 931 BOOST_UBLAS_INLINE
Chris@16 932 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 933 typename self_type::
Chris@16 934 #endif
Chris@16 935 reverse_iterator2 rbegin () const {
Chris@16 936 return reverse_iterator2 (end ());
Chris@16 937 }
Chris@16 938 BOOST_UBLAS_INLINE
Chris@16 939 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 940 typename self_type::
Chris@16 941 #endif
Chris@16 942 reverse_iterator2 rend () const {
Chris@16 943 return reverse_iterator2 (begin ());
Chris@16 944 }
Chris@16 945 #endif
Chris@16 946
Chris@16 947 // Indices
Chris@16 948 BOOST_UBLAS_INLINE
Chris@16 949 size_type index1 () const {
Chris@16 950 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
Chris@16 951 if (rank_ == 1) {
Chris@16 952 const self_type &m = (*this) ();
Chris@16 953 BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
Chris@16 954 return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
Chris@16 955 } else {
Chris@16 956 return i_;
Chris@16 957 }
Chris@16 958 }
Chris@16 959 BOOST_UBLAS_INLINE
Chris@16 960 size_type index2 () const {
Chris@16 961 if (rank_ == 1) {
Chris@16 962 const self_type &m = (*this) ();
Chris@16 963 BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
Chris@16 964 return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
Chris@16 965 } else {
Chris@16 966 return j_;
Chris@16 967 }
Chris@16 968 }
Chris@16 969
Chris@16 970 // Assignment
Chris@16 971 BOOST_UBLAS_INLINE
Chris@16 972 iterator1 &operator = (const iterator1 &it) {
Chris@16 973 container_reference<self_type>::assign (&it ());
Chris@16 974 rank_ = it.rank_;
Chris@16 975 i_ = it.i_;
Chris@16 976 j_ = it.j_;
Chris@16 977 it_ = it.it_;
Chris@16 978 return *this;
Chris@16 979 }
Chris@16 980
Chris@16 981 // Comparison
Chris@16 982 BOOST_UBLAS_INLINE
Chris@16 983 bool operator == (const iterator1 &it) const {
Chris@16 984 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 985 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 986 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 987 return it_ == it.it_;
Chris@16 988 } else {
Chris@16 989 return i_ == it.i_ && j_ == it.j_;
Chris@16 990 }
Chris@16 991 }
Chris@16 992
Chris@16 993 private:
Chris@16 994 int rank_;
Chris@16 995 size_type i_;
Chris@16 996 size_type j_;
Chris@16 997 subiterator_type it_;
Chris@16 998
Chris@16 999 friend class const_iterator1;
Chris@16 1000 };
Chris@16 1001
Chris@16 1002 BOOST_UBLAS_INLINE
Chris@16 1003 iterator1 begin1 () {
Chris@16 1004 return find1 (0, 0, 0);
Chris@16 1005 }
Chris@16 1006 BOOST_UBLAS_INLINE
Chris@16 1007 iterator1 end1 () {
Chris@16 1008 return find1 (0, size1_, 0);
Chris@16 1009 }
Chris@16 1010
Chris@16 1011 class const_iterator2:
Chris@16 1012 public container_const_reference<mapped_matrix>,
Chris@16 1013 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 1014 const_iterator2, value_type> {
Chris@16 1015 public:
Chris@16 1016 typedef typename mapped_matrix::value_type value_type;
Chris@16 1017 typedef typename mapped_matrix::difference_type difference_type;
Chris@16 1018 typedef typename mapped_matrix::const_reference reference;
Chris@16 1019 typedef const typename mapped_matrix::pointer pointer;
Chris@16 1020
Chris@16 1021 typedef const_iterator1 dual_iterator_type;
Chris@16 1022 typedef const_reverse_iterator1 dual_reverse_iterator_type;
Chris@16 1023
Chris@16 1024 // Construction and destruction
Chris@16 1025 BOOST_UBLAS_INLINE
Chris@16 1026 const_iterator2 ():
Chris@16 1027 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
Chris@16 1028 BOOST_UBLAS_INLINE
Chris@16 1029 const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_subiterator_type &it):
Chris@16 1030 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
Chris@16 1031 BOOST_UBLAS_INLINE
Chris@16 1032 const_iterator2 (const iterator2 &it):
Chris@16 1033 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
Chris@16 1034
Chris@16 1035 // Arithmetic
Chris@16 1036 BOOST_UBLAS_INLINE
Chris@16 1037 const_iterator2 &operator ++ () {
Chris@16 1038 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 1039 ++ it_;
Chris@16 1040 else
Chris@16 1041 *this = (*this) ().find2 (rank_, i_, index2 () + 1, 1);
Chris@16 1042 return *this;
Chris@16 1043 }
Chris@16 1044 BOOST_UBLAS_INLINE
Chris@16 1045 const_iterator2 &operator -- () {
Chris@16 1046 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 1047 -- it_;
Chris@16 1048 else
Chris@16 1049 *this = (*this) ().find2 (rank_, i_, index2 () - 1, -1);
Chris@16 1050 return *this;
Chris@16 1051 }
Chris@16 1052
Chris@16 1053 // Dereference
Chris@16 1054 BOOST_UBLAS_INLINE
Chris@16 1055 const_reference operator * () const {
Chris@16 1056 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 1057 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 1058 if (rank_ == 1) {
Chris@16 1059 return (*it_).second;
Chris@16 1060 } else {
Chris@16 1061 return (*this) () (i_, j_);
Chris@16 1062 }
Chris@16 1063 }
Chris@16 1064
Chris@16 1065 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 1066 BOOST_UBLAS_INLINE
Chris@16 1067 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 1068 typename self_type::
Chris@16 1069 #endif
Chris@16 1070 const_iterator1 begin () const {
Chris@16 1071 const self_type &m = (*this) ();
Chris@16 1072 return m.find1 (1, 0, index2 ());
Chris@16 1073 }
Chris@16 1074 BOOST_UBLAS_INLINE
Chris@16 1075 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 1076 typename self_type::
Chris@16 1077 #endif
Chris@101 1078 const_iterator1 cbegin () const {
Chris@101 1079 return begin ();
Chris@101 1080 }
Chris@101 1081 BOOST_UBLAS_INLINE
Chris@101 1082 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 1083 typename self_type::
Chris@101 1084 #endif
Chris@16 1085 const_iterator1 end () const {
Chris@16 1086 const self_type &m = (*this) ();
Chris@16 1087 return m.find1 (1, m.size1 (), index2 ());
Chris@16 1088 }
Chris@16 1089 BOOST_UBLAS_INLINE
Chris@16 1090 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 1091 typename self_type::
Chris@16 1092 #endif
Chris@101 1093 const_iterator1 cend () const {
Chris@101 1094 return end ();
Chris@101 1095 }
Chris@101 1096 BOOST_UBLAS_INLINE
Chris@101 1097 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 1098 typename self_type::
Chris@101 1099 #endif
Chris@16 1100 const_reverse_iterator1 rbegin () const {
Chris@16 1101 return const_reverse_iterator1 (end ());
Chris@16 1102 }
Chris@16 1103 BOOST_UBLAS_INLINE
Chris@16 1104 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 1105 typename self_type::
Chris@16 1106 #endif
Chris@101 1107 const_reverse_iterator1 crbegin () const {
Chris@101 1108 return rbegin ();
Chris@101 1109 }
Chris@101 1110 BOOST_UBLAS_INLINE
Chris@101 1111 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 1112 typename self_type::
Chris@101 1113 #endif
Chris@16 1114 const_reverse_iterator1 rend () const {
Chris@16 1115 return const_reverse_iterator1 (begin ());
Chris@16 1116 }
Chris@101 1117 BOOST_UBLAS_INLINE
Chris@101 1118 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 1119 typename self_type::
Chris@101 1120 #endif
Chris@101 1121 const_reverse_iterator1 crend () const {
Chris@101 1122 return rend ();
Chris@101 1123 }
Chris@16 1124 #endif
Chris@16 1125
Chris@16 1126 // Indices
Chris@16 1127 BOOST_UBLAS_INLINE
Chris@16 1128 size_type index1 () const {
Chris@16 1129 if (rank_ == 1) {
Chris@16 1130 const self_type &m = (*this) ();
Chris@16 1131 BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
Chris@16 1132 return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
Chris@16 1133 } else {
Chris@16 1134 return i_;
Chris@16 1135 }
Chris@16 1136 }
Chris@16 1137 BOOST_UBLAS_INLINE
Chris@16 1138 size_type index2 () const {
Chris@16 1139 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
Chris@16 1140 if (rank_ == 1) {
Chris@16 1141 const self_type &m = (*this) ();
Chris@16 1142 BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
Chris@16 1143 return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
Chris@16 1144 } else {
Chris@16 1145 return j_;
Chris@16 1146 }
Chris@16 1147 }
Chris@16 1148
Chris@16 1149 // Assignment
Chris@16 1150 BOOST_UBLAS_INLINE
Chris@16 1151 const_iterator2 &operator = (const const_iterator2 &it) {
Chris@16 1152 container_const_reference<self_type>::assign (&it ());
Chris@16 1153 rank_ = it.rank_;
Chris@16 1154 i_ = it.i_;
Chris@16 1155 j_ = it.j_;
Chris@16 1156 it_ = it.it_;
Chris@16 1157 return *this;
Chris@16 1158 }
Chris@16 1159
Chris@16 1160 // Comparison
Chris@16 1161 BOOST_UBLAS_INLINE
Chris@16 1162 bool operator == (const const_iterator2 &it) const {
Chris@16 1163 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 1164 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 1165 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 1166 return it_ == it.it_;
Chris@16 1167 } else {
Chris@16 1168 return i_ == it.i_ && j_ == it.j_;
Chris@16 1169 }
Chris@16 1170 }
Chris@16 1171
Chris@16 1172 private:
Chris@16 1173 int rank_;
Chris@16 1174 size_type i_;
Chris@16 1175 size_type j_;
Chris@16 1176 const_subiterator_type it_;
Chris@16 1177 };
Chris@16 1178
Chris@16 1179 BOOST_UBLAS_INLINE
Chris@16 1180 const_iterator2 begin2 () const {
Chris@16 1181 return find2 (0, 0, 0);
Chris@16 1182 }
Chris@16 1183 BOOST_UBLAS_INLINE
Chris@101 1184 const_iterator2 cbegin2 () const {
Chris@101 1185 return begin2 ();
Chris@101 1186 }
Chris@101 1187 BOOST_UBLAS_INLINE
Chris@16 1188 const_iterator2 end2 () const {
Chris@16 1189 return find2 (0, 0, size2_);
Chris@16 1190 }
Chris@101 1191 BOOST_UBLAS_INLINE
Chris@101 1192 const_iterator2 cend2 () const {
Chris@101 1193 return end2 ();
Chris@101 1194 }
Chris@16 1195
Chris@16 1196 class iterator2:
Chris@16 1197 public container_reference<mapped_matrix>,
Chris@16 1198 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 1199 iterator2, value_type> {
Chris@16 1200 public:
Chris@16 1201 typedef typename mapped_matrix::value_type value_type;
Chris@16 1202 typedef typename mapped_matrix::difference_type difference_type;
Chris@16 1203 typedef typename mapped_matrix::true_reference reference;
Chris@16 1204 typedef typename mapped_matrix::pointer pointer;
Chris@16 1205
Chris@16 1206 typedef iterator1 dual_iterator_type;
Chris@16 1207 typedef reverse_iterator1 dual_reverse_iterator_type;
Chris@16 1208
Chris@16 1209 // Construction and destruction
Chris@16 1210 BOOST_UBLAS_INLINE
Chris@16 1211 iterator2 ():
Chris@16 1212 container_reference<self_type> (), rank_ (), i_ (), j_ (), it_ () {}
Chris@16 1213 BOOST_UBLAS_INLINE
Chris@16 1214 iterator2 (self_type &m, int rank, size_type i, size_type j, const subiterator_type &it):
Chris@16 1215 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), it_ (it) {}
Chris@16 1216
Chris@16 1217 // Arithmetic
Chris@16 1218 BOOST_UBLAS_INLINE
Chris@16 1219 iterator2 &operator ++ () {
Chris@16 1220 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 1221 ++ it_;
Chris@16 1222 else
Chris@16 1223 *this = (*this) ().find2 (rank_, i_, index2 () + 1, 1);
Chris@16 1224 return *this;
Chris@16 1225 }
Chris@16 1226 BOOST_UBLAS_INLINE
Chris@16 1227 iterator2 &operator -- () {
Chris@16 1228 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 1229 -- it_;
Chris@16 1230 else
Chris@16 1231 *this = (*this) ().find2 (rank_, i_, index2 () - 1, -1);
Chris@16 1232 return *this;
Chris@16 1233 }
Chris@16 1234
Chris@16 1235 // Dereference
Chris@16 1236 BOOST_UBLAS_INLINE
Chris@16 1237 reference operator * () const {
Chris@16 1238 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 1239 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 1240 if (rank_ == 1) {
Chris@16 1241 return (*it_).second;
Chris@16 1242 } else {
Chris@16 1243 return (*this) ().at_element (i_, j_);
Chris@16 1244 }
Chris@16 1245 }
Chris@16 1246
Chris@16 1247 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 1248 BOOST_UBLAS_INLINE
Chris@16 1249 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 1250 typename self_type::
Chris@16 1251 #endif
Chris@16 1252 iterator1 begin () const {
Chris@16 1253 self_type &m = (*this) ();
Chris@16 1254 return m.find1 (1, 0, index2 ());
Chris@16 1255 }
Chris@16 1256 BOOST_UBLAS_INLINE
Chris@16 1257 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 1258 typename self_type::
Chris@16 1259 #endif
Chris@16 1260 iterator1 end () const {
Chris@16 1261 self_type &m = (*this) ();
Chris@16 1262 return m.find1 (1, m.size1 (), index2 ());
Chris@16 1263 }
Chris@16 1264 BOOST_UBLAS_INLINE
Chris@16 1265 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 1266 typename self_type::
Chris@16 1267 #endif
Chris@16 1268 reverse_iterator1 rbegin () const {
Chris@16 1269 return reverse_iterator1 (end ());
Chris@16 1270 }
Chris@16 1271 BOOST_UBLAS_INLINE
Chris@16 1272 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 1273 typename self_type::
Chris@16 1274 #endif
Chris@16 1275 reverse_iterator1 rend () const {
Chris@16 1276 return reverse_iterator1 (begin ());
Chris@16 1277 }
Chris@16 1278 #endif
Chris@16 1279
Chris@16 1280 // Indices
Chris@16 1281 BOOST_UBLAS_INLINE
Chris@16 1282 size_type index1 () const {
Chris@16 1283 if (rank_ == 1) {
Chris@16 1284 const self_type &m = (*this) ();
Chris@16 1285 BOOST_UBLAS_CHECK (layout_type::index_i ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size1 (), bad_index ());
Chris@16 1286 return layout_type::index_i ((*it_).first, m.size1 (), m.size2 ());
Chris@16 1287 } else {
Chris@16 1288 return i_;
Chris@16 1289 }
Chris@16 1290 }
Chris@16 1291 BOOST_UBLAS_INLINE
Chris@16 1292 size_type index2 () const {
Chris@16 1293 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
Chris@16 1294 if (rank_ == 1) {
Chris@16 1295 const self_type &m = (*this) ();
Chris@16 1296 BOOST_UBLAS_CHECK (layout_type::index_j ((*it_).first, m.size1 (), m.size2 ()) < (*this) ().size2 (), bad_index ());
Chris@16 1297 return layout_type::index_j ((*it_).first, m.size1 (), m.size2 ());
Chris@16 1298 } else {
Chris@16 1299 return j_;
Chris@16 1300 }
Chris@16 1301 }
Chris@16 1302
Chris@16 1303 // Assignment
Chris@16 1304 BOOST_UBLAS_INLINE
Chris@16 1305 iterator2 &operator = (const iterator2 &it) {
Chris@16 1306 container_reference<self_type>::assign (&it ());
Chris@16 1307 rank_ = it.rank_;
Chris@16 1308 i_ = it.i_;
Chris@16 1309 j_ = it.j_;
Chris@16 1310 it_ = it.it_;
Chris@16 1311 return *this;
Chris@16 1312 }
Chris@16 1313
Chris@16 1314 // Comparison
Chris@16 1315 BOOST_UBLAS_INLINE
Chris@16 1316 bool operator == (const iterator2 &it) const {
Chris@16 1317 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 1318 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 1319 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 1320 return it_ == it.it_;
Chris@16 1321 } else {
Chris@16 1322 return i_ == it.i_ && j_ == it.j_;
Chris@16 1323 }
Chris@16 1324 }
Chris@16 1325
Chris@16 1326 private:
Chris@16 1327 int rank_;
Chris@16 1328 size_type i_;
Chris@16 1329 size_type j_;
Chris@16 1330 subiterator_type it_;
Chris@16 1331
Chris@16 1332 friend class const_iterator2;
Chris@16 1333 };
Chris@16 1334
Chris@16 1335 BOOST_UBLAS_INLINE
Chris@16 1336 iterator2 begin2 () {
Chris@16 1337 return find2 (0, 0, 0);
Chris@16 1338 }
Chris@16 1339 BOOST_UBLAS_INLINE
Chris@16 1340 iterator2 end2 () {
Chris@16 1341 return find2 (0, 0, size2_);
Chris@16 1342 }
Chris@16 1343
Chris@16 1344 // Reverse iterators
Chris@16 1345
Chris@16 1346 BOOST_UBLAS_INLINE
Chris@16 1347 const_reverse_iterator1 rbegin1 () const {
Chris@16 1348 return const_reverse_iterator1 (end1 ());
Chris@16 1349 }
Chris@16 1350 BOOST_UBLAS_INLINE
Chris@101 1351 const_reverse_iterator1 crbegin1 () const {
Chris@101 1352 return rbegin1 ();
Chris@101 1353 }
Chris@101 1354 BOOST_UBLAS_INLINE
Chris@16 1355 const_reverse_iterator1 rend1 () const {
Chris@16 1356 return const_reverse_iterator1 (begin1 ());
Chris@16 1357 }
Chris@101 1358 BOOST_UBLAS_INLINE
Chris@101 1359 const_reverse_iterator1 crend1 () const {
Chris@101 1360 return rend1 ();
Chris@101 1361 }
Chris@16 1362
Chris@16 1363 BOOST_UBLAS_INLINE
Chris@16 1364 reverse_iterator1 rbegin1 () {
Chris@16 1365 return reverse_iterator1 (end1 ());
Chris@16 1366 }
Chris@16 1367 BOOST_UBLAS_INLINE
Chris@16 1368 reverse_iterator1 rend1 () {
Chris@16 1369 return reverse_iterator1 (begin1 ());
Chris@16 1370 }
Chris@16 1371
Chris@16 1372 BOOST_UBLAS_INLINE
Chris@16 1373 const_reverse_iterator2 rbegin2 () const {
Chris@16 1374 return const_reverse_iterator2 (end2 ());
Chris@16 1375 }
Chris@16 1376 BOOST_UBLAS_INLINE
Chris@101 1377 const_reverse_iterator2 crbegin2 () const {
Chris@101 1378 return rbegin2 ();
Chris@101 1379 }
Chris@101 1380 BOOST_UBLAS_INLINE
Chris@16 1381 const_reverse_iterator2 rend2 () const {
Chris@16 1382 return const_reverse_iterator2 (begin2 ());
Chris@16 1383 }
Chris@101 1384 BOOST_UBLAS_INLINE
Chris@101 1385 const_reverse_iterator2 crend2 () const {
Chris@101 1386 return rend2 ();
Chris@101 1387 }
Chris@16 1388
Chris@16 1389 BOOST_UBLAS_INLINE
Chris@16 1390 reverse_iterator2 rbegin2 () {
Chris@16 1391 return reverse_iterator2 (end2 ());
Chris@16 1392 }
Chris@16 1393 BOOST_UBLAS_INLINE
Chris@16 1394 reverse_iterator2 rend2 () {
Chris@16 1395 return reverse_iterator2 (begin2 ());
Chris@16 1396 }
Chris@16 1397
Chris@16 1398 // Serialization
Chris@16 1399 template<class Archive>
Chris@16 1400 void serialize(Archive & ar, const unsigned int /* file_version */){
Chris@16 1401 serialization::collection_size_type s1 (size1_);
Chris@16 1402 serialization::collection_size_type s2 (size2_);
Chris@16 1403 ar & serialization::make_nvp("size1",s1);
Chris@16 1404 ar & serialization::make_nvp("size2",s2);
Chris@16 1405 if (Archive::is_loading::value) {
Chris@16 1406 size1_ = s1;
Chris@16 1407 size2_ = s2;
Chris@16 1408 }
Chris@16 1409 ar & serialization::make_nvp("data", data_);
Chris@16 1410 }
Chris@16 1411
Chris@16 1412 private:
Chris@16 1413 size_type size1_;
Chris@16 1414 size_type size2_;
Chris@16 1415 array_type data_;
Chris@16 1416 static const value_type zero_;
Chris@16 1417 };
Chris@16 1418
Chris@16 1419 template<class T, class L, class A>
Chris@16 1420 const typename mapped_matrix<T, L, A>::value_type mapped_matrix<T, L, A>::zero_ = value_type/*zero*/();
Chris@16 1421
Chris@16 1422
Chris@16 1423 // Vector index map based sparse matrix class
Chris@16 1424 template<class T, class L, class A>
Chris@16 1425 class mapped_vector_of_mapped_vector:
Chris@16 1426 public matrix_container<mapped_vector_of_mapped_vector<T, L, A> > {
Chris@16 1427
Chris@16 1428 typedef T &true_reference;
Chris@16 1429 typedef T *pointer;
Chris@16 1430 typedef const T *const_pointer;
Chris@16 1431 typedef A array_type;
Chris@16 1432 typedef const A const_array_type;
Chris@16 1433 typedef L layout_type;
Chris@16 1434 typedef mapped_vector_of_mapped_vector<T, L, A> self_type;
Chris@16 1435 public:
Chris@16 1436 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
Chris@16 1437 using matrix_container<self_type>::operator ();
Chris@16 1438 #endif
Chris@16 1439 typedef typename A::size_type size_type;
Chris@16 1440 typedef typename A::difference_type difference_type;
Chris@16 1441 typedef T value_type;
Chris@16 1442 typedef const T &const_reference;
Chris@16 1443 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
Chris@16 1444 typedef typename detail::map_traits<typename A::data_value_type, T>::reference reference;
Chris@16 1445 #else
Chris@16 1446 typedef sparse_matrix_element<self_type> reference;
Chris@16 1447 #endif
Chris@16 1448 typedef const matrix_reference<const self_type> const_closure_type;
Chris@16 1449 typedef matrix_reference<self_type> closure_type;
Chris@16 1450 typedef mapped_vector<T> vector_temporary_type;
Chris@16 1451 typedef self_type matrix_temporary_type;
Chris@16 1452 typedef typename A::value_type::second_type vector_data_value_type;
Chris@16 1453 typedef sparse_tag storage_category;
Chris@16 1454 typedef typename L::orientation_category orientation_category;
Chris@16 1455
Chris@16 1456 // Construction and destruction
Chris@16 1457 BOOST_UBLAS_INLINE
Chris@16 1458 mapped_vector_of_mapped_vector ():
Chris@16 1459 matrix_container<self_type> (),
Chris@16 1460 size1_ (0), size2_ (0), data_ () {
Chris@16 1461 data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
Chris@16 1462 }
Chris@16 1463 BOOST_UBLAS_INLINE
Chris@16 1464 mapped_vector_of_mapped_vector (size_type size1, size_type size2, size_type non_zeros = 0):
Chris@16 1465 matrix_container<self_type> (),
Chris@16 1466 size1_ (size1), size2_ (size2), data_ () {
Chris@16 1467 data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
Chris@16 1468 }
Chris@16 1469 BOOST_UBLAS_INLINE
Chris@16 1470 mapped_vector_of_mapped_vector (const mapped_vector_of_mapped_vector &m):
Chris@16 1471 matrix_container<self_type> (),
Chris@16 1472 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
Chris@16 1473 template<class AE>
Chris@16 1474 BOOST_UBLAS_INLINE
Chris@16 1475 mapped_vector_of_mapped_vector (const matrix_expression<AE> &ae, size_type non_zeros = 0):
Chris@16 1476 matrix_container<self_type> (),
Chris@16 1477 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ () {
Chris@16 1478 data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
Chris@16 1479 matrix_assign<scalar_assign> (*this, ae);
Chris@16 1480 }
Chris@16 1481
Chris@16 1482 // Accessors
Chris@16 1483 BOOST_UBLAS_INLINE
Chris@16 1484 size_type size1 () const {
Chris@16 1485 return size1_;
Chris@16 1486 }
Chris@16 1487 BOOST_UBLAS_INLINE
Chris@16 1488 size_type size2 () const {
Chris@16 1489 return size2_;
Chris@16 1490 }
Chris@16 1491 BOOST_UBLAS_INLINE
Chris@16 1492 size_type nnz_capacity () const {
Chris@16 1493 size_type non_zeros = 0;
Chris@16 1494 for (vector_const_subiterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv)
Chris@16 1495 non_zeros += detail::map_capacity (*itv);
Chris@16 1496 return non_zeros;
Chris@16 1497 }
Chris@16 1498 BOOST_UBLAS_INLINE
Chris@16 1499 size_type nnz () const {
Chris@16 1500 size_type filled = 0;
Chris@16 1501 for (vector_const_subiterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv)
Chris@16 1502 filled += (*itv).size ();
Chris@16 1503 return filled;
Chris@16 1504 }
Chris@16 1505
Chris@16 1506 // Storage accessors
Chris@16 1507 BOOST_UBLAS_INLINE
Chris@16 1508 const_array_type &data () const {
Chris@16 1509 return data_;
Chris@16 1510 }
Chris@16 1511 BOOST_UBLAS_INLINE
Chris@16 1512 array_type &data () {
Chris@16 1513 return data_;
Chris@16 1514 }
Chris@16 1515
Chris@16 1516 // Resizing
Chris@16 1517 BOOST_UBLAS_INLINE
Chris@16 1518 void resize (size_type size1, size_type size2, bool preserve = true) {
Chris@16 1519 // FIXME preserve unimplemented
Chris@16 1520 BOOST_UBLAS_CHECK (!preserve, internal_logic ());
Chris@16 1521 size1_ = size1;
Chris@16 1522 size2_ = size2;
Chris@16 1523 data ().clear ();
Chris@16 1524 data () [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
Chris@16 1525 }
Chris@16 1526
Chris@16 1527 // Element support
Chris@16 1528 BOOST_UBLAS_INLINE
Chris@16 1529 pointer find_element (size_type i, size_type j) {
Chris@16 1530 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
Chris@16 1531 }
Chris@16 1532 BOOST_UBLAS_INLINE
Chris@16 1533 const_pointer find_element (size_type i, size_type j) const {
Chris@16 1534 const size_type element1 = layout_type::index_M (i, j);
Chris@16 1535 const size_type element2 = layout_type::index_m (i, j);
Chris@16 1536 vector_const_subiterator_type itv (data ().find (element1));
Chris@16 1537 if (itv == data ().end ())
Chris@16 1538 return 0;
Chris@16 1539 BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map
Chris@16 1540 const_subiterator_type it ((*itv).second.find (element2));
Chris@16 1541 if (it == (*itv).second.end ())
Chris@16 1542 return 0;
Chris@16 1543 BOOST_UBLAS_CHECK ((*it).first == element2, internal_logic ()); // broken map
Chris@16 1544 return &(*it).second;
Chris@16 1545 }
Chris@16 1546
Chris@16 1547 // Element access
Chris@16 1548 BOOST_UBLAS_INLINE
Chris@16 1549 const_reference operator () (size_type i, size_type j) const {
Chris@16 1550 const size_type element1 = layout_type::index_M (i, j);
Chris@16 1551 const size_type element2 = layout_type::index_m (i, j);
Chris@16 1552 vector_const_subiterator_type itv (data ().find (element1));
Chris@16 1553 if (itv == data ().end ())
Chris@16 1554 return zero_;
Chris@16 1555 BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map
Chris@16 1556 const_subiterator_type it ((*itv).second.find (element2));
Chris@16 1557 if (it == (*itv).second.end ())
Chris@16 1558 return zero_;
Chris@16 1559 BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map
Chris@16 1560 return (*it).second;
Chris@16 1561 }
Chris@16 1562 BOOST_UBLAS_INLINE
Chris@16 1563 reference operator () (size_type i, size_type j) {
Chris@16 1564 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
Chris@16 1565 const size_type element1 = layout_type::index_M (i, j);
Chris@16 1566 const size_type element2 = layout_type::index_m (i, j);
Chris@16 1567 vector_data_value_type& vd (data () [element1]);
Chris@16 1568 std::pair<subiterator_type, bool> ii (vd.insert (typename array_type::value_type::second_type::value_type (element2, value_type/*zero*/())));
Chris@16 1569 BOOST_UBLAS_CHECK ((ii.first)->first == element2, internal_logic ()); // broken map
Chris@16 1570 return (ii.first)->second;
Chris@16 1571 #else
Chris@16 1572 return reference (*this, i, j);
Chris@16 1573 #endif
Chris@16 1574 }
Chris@16 1575
Chris@16 1576 // Element assignment
Chris@16 1577 BOOST_UBLAS_INLINE
Chris@16 1578 true_reference insert_element (size_type i, size_type j, const_reference t) {
Chris@16 1579 BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
Chris@16 1580 const size_type element1 = layout_type::index_M (i, j);
Chris@16 1581 const size_type element2 = layout_type::index_m (i, j);
Chris@16 1582
Chris@16 1583 vector_data_value_type& vd (data () [element1]);
Chris@16 1584 std::pair<subiterator_type, bool> ii (vd.insert (typename vector_data_value_type::value_type (element2, t)));
Chris@16 1585 BOOST_UBLAS_CHECK ((ii.first)->first == element2, internal_logic ()); // broken map
Chris@16 1586 if (!ii.second) // existing element
Chris@16 1587 (ii.first)->second = t;
Chris@16 1588 return (ii.first)->second;
Chris@16 1589 }
Chris@16 1590 BOOST_UBLAS_INLINE
Chris@16 1591 void erase_element (size_type i, size_type j) {
Chris@16 1592 vector_subiterator_type itv (data ().find (layout_type::index_M (i, j)));
Chris@16 1593 if (itv == data ().end ())
Chris@16 1594 return;
Chris@16 1595 subiterator_type it ((*itv).second.find (layout_type::index_m (i, j)));
Chris@16 1596 if (it == (*itv).second.end ())
Chris@16 1597 return;
Chris@16 1598 (*itv).second.erase (it);
Chris@16 1599 }
Chris@16 1600
Chris@16 1601 // Zeroing
Chris@16 1602 BOOST_UBLAS_INLINE
Chris@16 1603 void clear () {
Chris@16 1604 data ().clear ();
Chris@16 1605 data_ [layout_type::size_M (size1_, size2_)] = vector_data_value_type ();
Chris@16 1606 }
Chris@16 1607
Chris@16 1608 // Assignment
Chris@16 1609 BOOST_UBLAS_INLINE
Chris@16 1610 mapped_vector_of_mapped_vector &operator = (const mapped_vector_of_mapped_vector &m) {
Chris@16 1611 if (this != &m) {
Chris@16 1612 size1_ = m.size1_;
Chris@16 1613 size2_ = m.size2_;
Chris@16 1614 data () = m.data ();
Chris@16 1615 }
Chris@16 1616 return *this;
Chris@16 1617 }
Chris@16 1618 template<class C> // Container assignment without temporary
Chris@16 1619 BOOST_UBLAS_INLINE
Chris@16 1620 mapped_vector_of_mapped_vector &operator = (const matrix_container<C> &m) {
Chris@16 1621 resize (m ().size1 (), m ().size2 (), false);
Chris@16 1622 assign (m);
Chris@16 1623 return *this;
Chris@16 1624 }
Chris@16 1625 BOOST_UBLAS_INLINE
Chris@16 1626 mapped_vector_of_mapped_vector &assign_temporary (mapped_vector_of_mapped_vector &m) {
Chris@16 1627 swap (m);
Chris@16 1628 return *this;
Chris@16 1629 }
Chris@16 1630 template<class AE>
Chris@16 1631 BOOST_UBLAS_INLINE
Chris@16 1632 mapped_vector_of_mapped_vector &operator = (const matrix_expression<AE> &ae) {
Chris@16 1633 self_type temporary (ae);
Chris@16 1634 return assign_temporary (temporary);
Chris@16 1635 }
Chris@16 1636 template<class AE>
Chris@16 1637 BOOST_UBLAS_INLINE
Chris@16 1638 mapped_vector_of_mapped_vector &assign (const matrix_expression<AE> &ae) {
Chris@16 1639 matrix_assign<scalar_assign> (*this, ae);
Chris@16 1640 return *this;
Chris@16 1641 }
Chris@16 1642 template<class AE>
Chris@16 1643 BOOST_UBLAS_INLINE
Chris@16 1644 mapped_vector_of_mapped_vector& operator += (const matrix_expression<AE> &ae) {
Chris@16 1645 self_type temporary (*this + ae);
Chris@16 1646 return assign_temporary (temporary);
Chris@16 1647 }
Chris@16 1648 template<class C> // Container assignment without temporary
Chris@16 1649 BOOST_UBLAS_INLINE
Chris@16 1650 mapped_vector_of_mapped_vector &operator += (const matrix_container<C> &m) {
Chris@16 1651 plus_assign (m);
Chris@16 1652 return *this;
Chris@16 1653 }
Chris@16 1654 template<class AE>
Chris@16 1655 BOOST_UBLAS_INLINE
Chris@16 1656 mapped_vector_of_mapped_vector &plus_assign (const matrix_expression<AE> &ae) {
Chris@16 1657 matrix_assign<scalar_plus_assign> (*this, ae);
Chris@16 1658 return *this;
Chris@16 1659 }
Chris@16 1660 template<class AE>
Chris@16 1661 BOOST_UBLAS_INLINE
Chris@16 1662 mapped_vector_of_mapped_vector& operator -= (const matrix_expression<AE> &ae) {
Chris@16 1663 self_type temporary (*this - ae);
Chris@16 1664 return assign_temporary (temporary);
Chris@16 1665 }
Chris@16 1666 template<class C> // Container assignment without temporary
Chris@16 1667 BOOST_UBLAS_INLINE
Chris@16 1668 mapped_vector_of_mapped_vector &operator -= (const matrix_container<C> &m) {
Chris@16 1669 minus_assign (m);
Chris@16 1670 return *this;
Chris@16 1671 }
Chris@16 1672 template<class AE>
Chris@16 1673 BOOST_UBLAS_INLINE
Chris@16 1674 mapped_vector_of_mapped_vector &minus_assign (const matrix_expression<AE> &ae) {
Chris@16 1675 matrix_assign<scalar_minus_assign> (*this, ae);
Chris@16 1676 return *this;
Chris@16 1677 }
Chris@16 1678 template<class AT>
Chris@16 1679 BOOST_UBLAS_INLINE
Chris@16 1680 mapped_vector_of_mapped_vector& operator *= (const AT &at) {
Chris@16 1681 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
Chris@16 1682 return *this;
Chris@16 1683 }
Chris@16 1684 template<class AT>
Chris@16 1685 BOOST_UBLAS_INLINE
Chris@16 1686 mapped_vector_of_mapped_vector& operator /= (const AT &at) {
Chris@16 1687 matrix_assign_scalar<scalar_divides_assign> (*this, at);
Chris@16 1688 return *this;
Chris@16 1689 }
Chris@16 1690
Chris@16 1691 // Swapping
Chris@16 1692 BOOST_UBLAS_INLINE
Chris@16 1693 void swap (mapped_vector_of_mapped_vector &m) {
Chris@16 1694 if (this != &m) {
Chris@16 1695 std::swap (size1_, m.size1_);
Chris@16 1696 std::swap (size2_, m.size2_);
Chris@16 1697 data ().swap (m.data ());
Chris@16 1698 }
Chris@16 1699 }
Chris@16 1700 BOOST_UBLAS_INLINE
Chris@16 1701 friend void swap (mapped_vector_of_mapped_vector &m1, mapped_vector_of_mapped_vector &m2) {
Chris@16 1702 m1.swap (m2);
Chris@16 1703 }
Chris@16 1704
Chris@16 1705 // Iterator types
Chris@16 1706 private:
Chris@16 1707 // Use storage iterators
Chris@16 1708 typedef typename A::const_iterator vector_const_subiterator_type;
Chris@16 1709 typedef typename A::iterator vector_subiterator_type;
Chris@16 1710 typedef typename A::value_type::second_type::const_iterator const_subiterator_type;
Chris@16 1711 typedef typename A::value_type::second_type::iterator subiterator_type;
Chris@16 1712
Chris@16 1713 BOOST_UBLAS_INLINE
Chris@16 1714 true_reference at_element (size_type i, size_type j) {
Chris@16 1715 const size_type element1 = layout_type::index_M (i, j);
Chris@16 1716 const size_type element2 = layout_type::index_m (i, j);
Chris@16 1717 vector_subiterator_type itv (data ().find (element1));
Chris@16 1718 BOOST_UBLAS_CHECK (itv != data ().end(), bad_index ());
Chris@16 1719 BOOST_UBLAS_CHECK ((*itv).first == element1, internal_logic ()); // broken map
Chris@16 1720 subiterator_type it ((*itv).second.find (element2));
Chris@16 1721 BOOST_UBLAS_CHECK (it != (*itv).second.end (), bad_index ());
Chris@16 1722 BOOST_UBLAS_CHECK ((*it).first == element2, internal_logic ()); // broken map
Chris@16 1723
Chris@16 1724 return it->second;
Chris@16 1725 }
Chris@16 1726
Chris@16 1727 public:
Chris@16 1728 class const_iterator1;
Chris@16 1729 class iterator1;
Chris@16 1730 class const_iterator2;
Chris@16 1731 class iterator2;
Chris@16 1732 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
Chris@16 1733 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
Chris@16 1734 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
Chris@16 1735 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
Chris@16 1736
Chris@16 1737 // Element lookup
Chris@16 1738 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 1739 const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
Chris@16 1740 BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
Chris@16 1741 for (;;) {
Chris@16 1742 vector_const_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
Chris@16 1743 vector_const_subiterator_type itv_end (data ().end ());
Chris@16 1744 if (itv == itv_end)
Chris@16 1745 return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
Chris@16 1746
Chris@16 1747 const_subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
Chris@16 1748 const_subiterator_type it_end ((*itv).second.end ());
Chris@16 1749 if (rank == 0) {
Chris@16 1750 // advance to the first available major index
Chris@16 1751 size_type M = itv->first;
Chris@16 1752 size_type m;
Chris@16 1753 if (it != it_end) {
Chris@16 1754 m = it->first;
Chris@16 1755 } else {
Chris@16 1756 m = layout_type::size_m(size1_, size2_);
Chris@16 1757 }
Chris@16 1758 size_type first_i = layout_type::index_M(M,m);
Chris@16 1759 return const_iterator1 (*this, rank, first_i, j, itv, it);
Chris@16 1760 }
Chris@16 1761 if (it != it_end && (*it).first == layout_type::index_m (i, j))
Chris@16 1762 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 1763 if (direction > 0) {
Chris@16 1764 if (layout_type::fast_i ()) {
Chris@16 1765 if (it == it_end)
Chris@16 1766 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 1767 i = (*it).first;
Chris@16 1768 } else {
Chris@16 1769 if (i >= size1_)
Chris@16 1770 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 1771 ++ i;
Chris@16 1772 }
Chris@16 1773 } else /* if (direction < 0) */ {
Chris@16 1774 if (layout_type::fast_i ()) {
Chris@16 1775 if (it == (*itv).second.begin ())
Chris@16 1776 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 1777 -- it;
Chris@16 1778 i = (*it).first;
Chris@16 1779 } else {
Chris@16 1780 if (i == 0)
Chris@16 1781 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 1782 -- i;
Chris@16 1783 }
Chris@16 1784 }
Chris@16 1785 }
Chris@16 1786 }
Chris@16 1787 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 1788 iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
Chris@16 1789 BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
Chris@16 1790 for (;;) {
Chris@16 1791 vector_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
Chris@16 1792 vector_subiterator_type itv_end (data ().end ());
Chris@16 1793 if (itv == itv_end)
Chris@16 1794 return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
Chris@16 1795
Chris@16 1796 subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
Chris@16 1797 subiterator_type it_end ((*itv).second.end ());
Chris@16 1798 if (rank == 0) {
Chris@16 1799 // advance to the first available major index
Chris@16 1800 size_type M = itv->first;
Chris@16 1801 size_type m;
Chris@16 1802 if (it != it_end) {
Chris@16 1803 m = it->first;
Chris@16 1804 } else {
Chris@16 1805 m = layout_type::size_m(size1_, size2_);
Chris@16 1806 }
Chris@16 1807 size_type first_i = layout_type::index_M(M,m);
Chris@16 1808 return iterator1 (*this, rank, first_i, j, itv, it);
Chris@16 1809 }
Chris@16 1810 if (it != it_end && (*it).first == layout_type::index_m (i, j))
Chris@16 1811 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 1812 if (direction > 0) {
Chris@16 1813 if (layout_type::fast_i ()) {
Chris@16 1814 if (it == it_end)
Chris@16 1815 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 1816 i = (*it).first;
Chris@16 1817 } else {
Chris@16 1818 if (i >= size1_)
Chris@16 1819 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 1820 ++ i;
Chris@16 1821 }
Chris@16 1822 } else /* if (direction < 0) */ {
Chris@16 1823 if (layout_type::fast_i ()) {
Chris@16 1824 if (it == (*itv).second.begin ())
Chris@16 1825 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 1826 -- it;
Chris@16 1827 i = (*it).first;
Chris@16 1828 } else {
Chris@16 1829 if (i == 0)
Chris@16 1830 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 1831 -- i;
Chris@16 1832 }
Chris@16 1833 }
Chris@16 1834 }
Chris@16 1835 }
Chris@16 1836 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 1837 const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
Chris@16 1838 BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
Chris@16 1839 for (;;) {
Chris@16 1840 vector_const_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
Chris@16 1841 vector_const_subiterator_type itv_end (data ().end ());
Chris@16 1842 if (itv == itv_end)
Chris@16 1843 return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
Chris@16 1844
Chris@16 1845 const_subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
Chris@16 1846 const_subiterator_type it_end ((*itv).second.end ());
Chris@16 1847 if (rank == 0) {
Chris@16 1848 // advance to the first available major index
Chris@16 1849 size_type M = itv->first;
Chris@16 1850 size_type m;
Chris@16 1851 if (it != it_end) {
Chris@16 1852 m = it->first;
Chris@16 1853 } else {
Chris@16 1854 m = layout_type::size_m(size1_, size2_);
Chris@16 1855 }
Chris@16 1856 size_type first_j = layout_type::index_m(M,m);
Chris@16 1857 return const_iterator2 (*this, rank, i, first_j, itv, it);
Chris@16 1858 }
Chris@16 1859 if (it != it_end && (*it).first == layout_type::index_m (i, j))
Chris@16 1860 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 1861 if (direction > 0) {
Chris@16 1862 if (layout_type::fast_j ()) {
Chris@16 1863 if (it == it_end)
Chris@16 1864 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 1865 j = (*it).first;
Chris@16 1866 } else {
Chris@16 1867 if (j >= size2_)
Chris@16 1868 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 1869 ++ j;
Chris@16 1870 }
Chris@16 1871 } else /* if (direction < 0) */ {
Chris@16 1872 if (layout_type::fast_j ()) {
Chris@16 1873 if (it == (*itv).second.begin ())
Chris@16 1874 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 1875 -- it;
Chris@16 1876 j = (*it).first;
Chris@16 1877 } else {
Chris@16 1878 if (j == 0)
Chris@16 1879 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 1880 -- j;
Chris@16 1881 }
Chris@16 1882 }
Chris@16 1883 }
Chris@16 1884 }
Chris@16 1885 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 1886 iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
Chris@16 1887 BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
Chris@16 1888 for (;;) {
Chris@16 1889 vector_subiterator_type itv (data ().lower_bound (layout_type::index_M (i, j)));
Chris@16 1890 vector_subiterator_type itv_end (data ().end ());
Chris@16 1891 if (itv == itv_end)
Chris@16 1892 return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).second.end ());
Chris@16 1893
Chris@16 1894 subiterator_type it ((*itv).second.lower_bound (layout_type::index_m (i, j)));
Chris@16 1895 subiterator_type it_end ((*itv).second.end ());
Chris@16 1896 if (rank == 0) {
Chris@16 1897 // advance to the first available major index
Chris@16 1898 size_type M = itv->first;
Chris@16 1899 size_type m;
Chris@16 1900 if (it != it_end) {
Chris@16 1901 m = it->first;
Chris@16 1902 } else {
Chris@16 1903 m = layout_type::size_m(size1_, size2_);
Chris@16 1904 }
Chris@16 1905 size_type first_j = layout_type::index_m(M,m);
Chris@16 1906 return iterator2 (*this, rank, i, first_j, itv, it);
Chris@16 1907 }
Chris@16 1908 if (it != it_end && (*it).first == layout_type::index_m (i, j))
Chris@16 1909 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 1910 if (direction > 0) {
Chris@16 1911 if (layout_type::fast_j ()) {
Chris@16 1912 if (it == it_end)
Chris@16 1913 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 1914 j = (*it).first;
Chris@16 1915 } else {
Chris@16 1916 if (j >= size2_)
Chris@16 1917 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 1918 ++ j;
Chris@16 1919 }
Chris@16 1920 } else /* if (direction < 0) */ {
Chris@16 1921 if (layout_type::fast_j ()) {
Chris@16 1922 if (it == (*itv).second.begin ())
Chris@16 1923 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 1924 -- it;
Chris@16 1925 j = (*it).first;
Chris@16 1926 } else {
Chris@16 1927 if (j == 0)
Chris@16 1928 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 1929 -- j;
Chris@16 1930 }
Chris@16 1931 }
Chris@16 1932 }
Chris@16 1933 }
Chris@16 1934
Chris@16 1935 class const_iterator1:
Chris@16 1936 public container_const_reference<mapped_vector_of_mapped_vector>,
Chris@16 1937 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 1938 const_iterator1, value_type> {
Chris@16 1939 public:
Chris@16 1940 typedef typename mapped_vector_of_mapped_vector::value_type value_type;
Chris@16 1941 typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
Chris@16 1942 typedef typename mapped_vector_of_mapped_vector::const_reference reference;
Chris@16 1943 typedef const typename mapped_vector_of_mapped_vector::pointer pointer;
Chris@16 1944
Chris@16 1945 typedef const_iterator2 dual_iterator_type;
Chris@16 1946 typedef const_reverse_iterator2 dual_reverse_iterator_type;
Chris@16 1947
Chris@16 1948 // Construction and destruction
Chris@16 1949 BOOST_UBLAS_INLINE
Chris@16 1950 const_iterator1 ():
Chris@16 1951 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
Chris@16 1952 BOOST_UBLAS_INLINE
Chris@16 1953 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):
Chris@16 1954 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
Chris@16 1955 BOOST_UBLAS_INLINE
Chris@16 1956 const_iterator1 (const iterator1 &it):
Chris@16 1957 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
Chris@16 1958
Chris@16 1959 // Arithmetic
Chris@16 1960 BOOST_UBLAS_INLINE
Chris@16 1961 const_iterator1 &operator ++ () {
Chris@16 1962 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 1963 ++ it_;
Chris@16 1964 else {
Chris@16 1965 const self_type &m = (*this) ();
Chris@16 1966 if (rank_ == 0) {
Chris@16 1967 ++ itv_;
Chris@16 1968 i_ = itv_->first;
Chris@16 1969 } else {
Chris@16 1970 i_ = index1 () + 1;
Chris@16 1971 }
Chris@16 1972 if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
Chris@16 1973 *this = m.find1 (rank_, i_, j_, 1);
Chris@16 1974 else if (rank_ == 1) {
Chris@16 1975 it_ = (*itv_).second.begin ();
Chris@16 1976 if (it_ == (*itv_).second.end () || index2 () != j_)
Chris@16 1977 *this = m.find1 (rank_, i_, j_, 1);
Chris@16 1978 }
Chris@16 1979 }
Chris@16 1980 return *this;
Chris@16 1981 }
Chris@16 1982 BOOST_UBLAS_INLINE
Chris@16 1983 const_iterator1 &operator -- () {
Chris@16 1984 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 1985 -- it_;
Chris@16 1986 else {
Chris@16 1987 const self_type &m = (*this) ();
Chris@16 1988 if (rank_ == 0) {
Chris@16 1989 -- itv_;
Chris@16 1990 i_ = itv_->first;
Chris@16 1991 } else {
Chris@16 1992 i_ = index1 () - 1;
Chris@16 1993 }
Chris@16 1994 // FIXME: this expression should never become true!
Chris@16 1995 if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
Chris@16 1996 *this = m.find1 (rank_, i_, j_, -1);
Chris@16 1997 else if (rank_ == 1) {
Chris@16 1998 it_ = (*itv_).second.begin ();
Chris@16 1999 if (it_ == (*itv_).second.end () || index2 () != j_)
Chris@16 2000 *this = m.find1 (rank_, i_, j_, -1);
Chris@16 2001 }
Chris@16 2002 }
Chris@16 2003 return *this;
Chris@16 2004 }
Chris@16 2005
Chris@16 2006 // Dereference
Chris@16 2007 BOOST_UBLAS_INLINE
Chris@16 2008 const_reference operator * () const {
Chris@16 2009 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 2010 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 2011 if (rank_ == 1) {
Chris@16 2012 return (*it_).second;
Chris@16 2013 } else {
Chris@16 2014 return (*this) () (i_, j_);
Chris@16 2015 }
Chris@16 2016 }
Chris@16 2017
Chris@16 2018 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 2019 BOOST_UBLAS_INLINE
Chris@16 2020 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2021 typename self_type::
Chris@16 2022 #endif
Chris@16 2023 const_iterator2 begin () const {
Chris@16 2024 const self_type &m = (*this) ();
Chris@16 2025 return m.find2 (1, index1 (), 0);
Chris@16 2026 }
Chris@16 2027 BOOST_UBLAS_INLINE
Chris@16 2028 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2029 typename self_type::
Chris@16 2030 #endif
Chris@101 2031 const_iterator2 cbegin () const {
Chris@101 2032 return begin ();
Chris@101 2033 }
Chris@101 2034 BOOST_UBLAS_INLINE
Chris@101 2035 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 2036 typename self_type::
Chris@101 2037 #endif
Chris@16 2038 const_iterator2 end () const {
Chris@16 2039 const self_type &m = (*this) ();
Chris@16 2040 return m.find2 (1, index1 (), m.size2 ());
Chris@16 2041 }
Chris@16 2042 BOOST_UBLAS_INLINE
Chris@16 2043 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2044 typename self_type::
Chris@16 2045 #endif
Chris@101 2046 const_iterator2 cend () const {
Chris@101 2047 return end ();
Chris@101 2048 }
Chris@101 2049 BOOST_UBLAS_INLINE
Chris@101 2050 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 2051 typename self_type::
Chris@101 2052 #endif
Chris@16 2053 const_reverse_iterator2 rbegin () const {
Chris@16 2054 return const_reverse_iterator2 (end ());
Chris@16 2055 }
Chris@16 2056 BOOST_UBLAS_INLINE
Chris@16 2057 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2058 typename self_type::
Chris@16 2059 #endif
Chris@101 2060 const_reverse_iterator2 crbegin () const {
Chris@101 2061 return rbegin ();
Chris@101 2062 }
Chris@101 2063 BOOST_UBLAS_INLINE
Chris@101 2064 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 2065 typename self_type::
Chris@101 2066 #endif
Chris@16 2067 const_reverse_iterator2 rend () const {
Chris@16 2068 return const_reverse_iterator2 (begin ());
Chris@16 2069 }
Chris@101 2070 BOOST_UBLAS_INLINE
Chris@101 2071 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 2072 typename self_type::
Chris@101 2073 #endif
Chris@101 2074 const_reverse_iterator2 crend () const {
Chris@101 2075 return rend ();
Chris@101 2076 }
Chris@16 2077 #endif
Chris@16 2078
Chris@16 2079 // Indices
Chris@16 2080 BOOST_UBLAS_INLINE
Chris@16 2081 size_type index1 () const {
Chris@16 2082 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
Chris@16 2083 if (rank_ == 1) {
Chris@16 2084 BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
Chris@16 2085 return layout_type::index_M ((*itv_).first, (*it_).first);
Chris@16 2086 } else {
Chris@16 2087 return i_;
Chris@16 2088 }
Chris@16 2089 }
Chris@16 2090 BOOST_UBLAS_INLINE
Chris@16 2091 size_type index2 () const {
Chris@16 2092 if (rank_ == 1) {
Chris@16 2093 BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
Chris@16 2094 return layout_type::index_m ((*itv_).first, (*it_).first);
Chris@16 2095 } else {
Chris@16 2096 return j_;
Chris@16 2097 }
Chris@16 2098 }
Chris@16 2099
Chris@16 2100 // Assignment
Chris@16 2101 BOOST_UBLAS_INLINE
Chris@16 2102 const_iterator1 &operator = (const const_iterator1 &it) {
Chris@16 2103 container_const_reference<self_type>::assign (&it ());
Chris@16 2104 rank_ = it.rank_;
Chris@16 2105 i_ = it.i_;
Chris@16 2106 j_ = it.j_;
Chris@16 2107 itv_ = it.itv_;
Chris@16 2108 it_ = it.it_;
Chris@16 2109 return *this;
Chris@16 2110 }
Chris@16 2111
Chris@16 2112 // Comparison
Chris@16 2113 BOOST_UBLAS_INLINE
Chris@16 2114 bool operator == (const const_iterator1 &it) const {
Chris@16 2115 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 2116 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 2117 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 2118 return it_ == it.it_;
Chris@16 2119 } else {
Chris@16 2120 return i_ == it.i_ && j_ == it.j_;
Chris@16 2121 }
Chris@16 2122 }
Chris@16 2123
Chris@16 2124 private:
Chris@16 2125 int rank_;
Chris@16 2126 size_type i_;
Chris@16 2127 size_type j_;
Chris@16 2128 vector_const_subiterator_type itv_;
Chris@16 2129 const_subiterator_type it_;
Chris@16 2130 };
Chris@16 2131
Chris@16 2132 BOOST_UBLAS_INLINE
Chris@16 2133 const_iterator1 begin1 () const {
Chris@16 2134 return find1 (0, 0, 0);
Chris@16 2135 }
Chris@16 2136 BOOST_UBLAS_INLINE
Chris@101 2137 const_iterator1 cbegin1 () const {
Chris@101 2138 return begin1 ();
Chris@101 2139 }
Chris@101 2140 BOOST_UBLAS_INLINE
Chris@16 2141 const_iterator1 end1 () const {
Chris@16 2142 return find1 (0, size1_, 0);
Chris@16 2143 }
Chris@101 2144 BOOST_UBLAS_INLINE
Chris@101 2145 const_iterator1 cend1 () const {
Chris@101 2146 return end1 ();
Chris@101 2147 }
Chris@16 2148
Chris@16 2149 class iterator1:
Chris@16 2150 public container_reference<mapped_vector_of_mapped_vector>,
Chris@16 2151 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 2152 iterator1, value_type> {
Chris@16 2153 public:
Chris@16 2154 typedef typename mapped_vector_of_mapped_vector::value_type value_type;
Chris@16 2155 typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
Chris@16 2156 typedef typename mapped_vector_of_mapped_vector::true_reference reference;
Chris@16 2157 typedef typename mapped_vector_of_mapped_vector::pointer pointer;
Chris@16 2158
Chris@16 2159 typedef iterator2 dual_iterator_type;
Chris@16 2160 typedef reverse_iterator2 dual_reverse_iterator_type;
Chris@16 2161
Chris@16 2162 // Construction and destruction
Chris@16 2163 BOOST_UBLAS_INLINE
Chris@16 2164 iterator1 ():
Chris@16 2165 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
Chris@16 2166 BOOST_UBLAS_INLINE
Chris@16 2167 iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
Chris@16 2168 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
Chris@16 2169
Chris@16 2170 // Arithmetic
Chris@16 2171 BOOST_UBLAS_INLINE
Chris@16 2172 iterator1 &operator ++ () {
Chris@16 2173 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 2174 ++ it_;
Chris@16 2175 else {
Chris@16 2176 self_type &m = (*this) ();
Chris@16 2177 if (rank_ == 0) {
Chris@16 2178 ++ itv_;
Chris@16 2179 i_ = itv_->first;
Chris@16 2180 } else {
Chris@16 2181 i_ = index1 () + 1;
Chris@16 2182 }
Chris@16 2183 if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
Chris@16 2184 *this = m.find1 (rank_, i_, j_, 1);
Chris@16 2185 else if (rank_ == 1) {
Chris@16 2186 it_ = (*itv_).second.begin ();
Chris@16 2187 if (it_ == (*itv_).second.end () || index2 () != j_)
Chris@16 2188 *this = m.find1 (rank_, i_, j_, 1);
Chris@16 2189 }
Chris@16 2190 }
Chris@16 2191 return *this;
Chris@16 2192 }
Chris@16 2193 BOOST_UBLAS_INLINE
Chris@16 2194 iterator1 &operator -- () {
Chris@16 2195 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 2196 -- it_;
Chris@16 2197 else {
Chris@16 2198 self_type &m = (*this) ();
Chris@16 2199 if (rank_ == 0) {
Chris@16 2200 -- itv_;
Chris@16 2201 i_ = itv_->first;
Chris@16 2202 } else {
Chris@16 2203 i_ = index1 () - 1;
Chris@16 2204 }
Chris@16 2205 // FIXME: this expression should never become true!
Chris@16 2206 if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
Chris@16 2207 *this = m.find1 (rank_, i_, j_, -1);
Chris@16 2208 else if (rank_ == 1) {
Chris@16 2209 it_ = (*itv_).second.begin ();
Chris@16 2210 if (it_ == (*itv_).second.end () || index2 () != j_)
Chris@16 2211 *this = m.find1 (rank_, i_, j_, -1);
Chris@16 2212 }
Chris@16 2213 }
Chris@16 2214 return *this;
Chris@16 2215 }
Chris@16 2216
Chris@16 2217 // Dereference
Chris@16 2218 BOOST_UBLAS_INLINE
Chris@16 2219 reference operator * () const {
Chris@16 2220 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 2221 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 2222 if (rank_ == 1) {
Chris@16 2223 return (*it_).second;
Chris@16 2224 } else {
Chris@16 2225 return (*this) ().at_element (i_, j_);
Chris@16 2226 }
Chris@16 2227 }
Chris@16 2228
Chris@16 2229 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 2230 BOOST_UBLAS_INLINE
Chris@16 2231 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2232 typename self_type::
Chris@16 2233 #endif
Chris@16 2234 iterator2 begin () const {
Chris@16 2235 self_type &m = (*this) ();
Chris@16 2236 return m.find2 (1, index1 (), 0);
Chris@16 2237 }
Chris@16 2238 BOOST_UBLAS_INLINE
Chris@16 2239 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2240 typename self_type::
Chris@16 2241 #endif
Chris@16 2242 iterator2 end () const {
Chris@16 2243 self_type &m = (*this) ();
Chris@16 2244 return m.find2 (1, index1 (), m.size2 ());
Chris@16 2245 }
Chris@16 2246 BOOST_UBLAS_INLINE
Chris@16 2247 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2248 typename self_type::
Chris@16 2249 #endif
Chris@16 2250 reverse_iterator2 rbegin () const {
Chris@16 2251 return reverse_iterator2 (end ());
Chris@16 2252 }
Chris@16 2253 BOOST_UBLAS_INLINE
Chris@16 2254 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2255 typename self_type::
Chris@16 2256 #endif
Chris@16 2257 reverse_iterator2 rend () const {
Chris@16 2258 return reverse_iterator2 (begin ());
Chris@16 2259 }
Chris@16 2260 #endif
Chris@16 2261
Chris@16 2262 // Indices
Chris@16 2263 BOOST_UBLAS_INLINE
Chris@16 2264 size_type index1 () const {
Chris@16 2265 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
Chris@16 2266 if (rank_ == 1) {
Chris@16 2267 BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
Chris@16 2268 return layout_type::index_M ((*itv_).first, (*it_).first);
Chris@16 2269 } else {
Chris@16 2270 return i_;
Chris@16 2271 }
Chris@16 2272 }
Chris@16 2273 BOOST_UBLAS_INLINE
Chris@16 2274 size_type index2 () const {
Chris@16 2275 if (rank_ == 1) {
Chris@16 2276 BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
Chris@16 2277 return layout_type::index_m ((*itv_).first, (*it_).first);
Chris@16 2278 } else {
Chris@16 2279 return j_;
Chris@16 2280 }
Chris@16 2281 }
Chris@16 2282
Chris@16 2283 // Assignment
Chris@16 2284 BOOST_UBLAS_INLINE
Chris@16 2285 iterator1 &operator = (const iterator1 &it) {
Chris@16 2286 container_reference<self_type>::assign (&it ());
Chris@16 2287 rank_ = it.rank_;
Chris@16 2288 i_ = it.i_;
Chris@16 2289 j_ = it.j_;
Chris@16 2290 itv_ = it.itv_;
Chris@16 2291 it_ = it.it_;
Chris@16 2292 return *this;
Chris@16 2293 }
Chris@16 2294
Chris@16 2295 // Comparison
Chris@16 2296 BOOST_UBLAS_INLINE
Chris@16 2297 bool operator == (const iterator1 &it) const {
Chris@16 2298 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 2299 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 2300 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 2301 return it_ == it.it_;
Chris@16 2302 } else {
Chris@16 2303 return i_ == it.i_ && j_ == it.j_;
Chris@16 2304 }
Chris@16 2305 }
Chris@16 2306
Chris@16 2307 private:
Chris@16 2308 int rank_;
Chris@16 2309 size_type i_;
Chris@16 2310 size_type j_;
Chris@16 2311 vector_subiterator_type itv_;
Chris@16 2312 subiterator_type it_;
Chris@16 2313
Chris@16 2314 friend class const_iterator1;
Chris@16 2315 };
Chris@16 2316
Chris@16 2317 BOOST_UBLAS_INLINE
Chris@16 2318 iterator1 begin1 () {
Chris@16 2319 return find1 (0, 0, 0);
Chris@16 2320 }
Chris@16 2321 BOOST_UBLAS_INLINE
Chris@16 2322 iterator1 end1 () {
Chris@16 2323 return find1 (0, size1_, 0);
Chris@16 2324 }
Chris@16 2325
Chris@16 2326 class const_iterator2:
Chris@16 2327 public container_const_reference<mapped_vector_of_mapped_vector>,
Chris@16 2328 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 2329 const_iterator2, value_type> {
Chris@16 2330 public:
Chris@16 2331 typedef typename mapped_vector_of_mapped_vector::value_type value_type;
Chris@16 2332 typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
Chris@16 2333 typedef typename mapped_vector_of_mapped_vector::const_reference reference;
Chris@16 2334 typedef const typename mapped_vector_of_mapped_vector::pointer pointer;
Chris@16 2335
Chris@16 2336 typedef const_iterator1 dual_iterator_type;
Chris@16 2337 typedef const_reverse_iterator1 dual_reverse_iterator_type;
Chris@16 2338
Chris@16 2339 // Construction and destruction
Chris@16 2340 BOOST_UBLAS_INLINE
Chris@16 2341 const_iterator2 ():
Chris@16 2342 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
Chris@16 2343 BOOST_UBLAS_INLINE
Chris@16 2344 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):
Chris@16 2345 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
Chris@16 2346 BOOST_UBLAS_INLINE
Chris@16 2347 const_iterator2 (const iterator2 &it):
Chris@16 2348 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
Chris@16 2349
Chris@16 2350 // Arithmetic
Chris@16 2351 BOOST_UBLAS_INLINE
Chris@16 2352 const_iterator2 &operator ++ () {
Chris@16 2353 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 2354 ++ it_;
Chris@16 2355 else {
Chris@16 2356 const self_type &m = (*this) ();
Chris@16 2357 if (rank_ == 0) {
Chris@16 2358 ++ itv_;
Chris@16 2359 j_ = itv_->first;
Chris@16 2360 } else {
Chris@16 2361 j_ = index2 () + 1;
Chris@16 2362 }
Chris@16 2363 if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
Chris@16 2364 *this = m.find2 (rank_, i_, j_, 1);
Chris@16 2365 else if (rank_ == 1) {
Chris@16 2366 it_ = (*itv_).second.begin ();
Chris@16 2367 if (it_ == (*itv_).second.end () || index1 () != i_)
Chris@16 2368 *this = m.find2 (rank_, i_, j_, 1);
Chris@16 2369 }
Chris@16 2370 }
Chris@16 2371 return *this;
Chris@16 2372 }
Chris@16 2373 BOOST_UBLAS_INLINE
Chris@16 2374 const_iterator2 &operator -- () {
Chris@16 2375 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 2376 -- it_;
Chris@16 2377 else {
Chris@16 2378 const self_type &m = (*this) ();
Chris@16 2379 if (rank_ == 0) {
Chris@16 2380 -- itv_;
Chris@16 2381 j_ = itv_->first;
Chris@16 2382 } else {
Chris@16 2383 j_ = index2 () - 1;
Chris@16 2384 }
Chris@16 2385 // FIXME: this expression should never become true!
Chris@16 2386 if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
Chris@16 2387 *this = m.find2 (rank_, i_, j_, -1);
Chris@16 2388 else if (rank_ == 1) {
Chris@16 2389 it_ = (*itv_).second.begin ();
Chris@16 2390 if (it_ == (*itv_).second.end () || index1 () != i_)
Chris@16 2391 *this = m.find2 (rank_, i_, j_, -1);
Chris@16 2392 }
Chris@16 2393 }
Chris@16 2394 return *this;
Chris@16 2395 }
Chris@16 2396
Chris@16 2397 // Dereference
Chris@16 2398 BOOST_UBLAS_INLINE
Chris@16 2399 const_reference operator * () const {
Chris@16 2400 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 2401 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 2402 if (rank_ == 1) {
Chris@16 2403 return (*it_).second;
Chris@16 2404 } else {
Chris@16 2405 return (*this) () (i_, j_);
Chris@16 2406 }
Chris@16 2407 }
Chris@16 2408
Chris@16 2409 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 2410 BOOST_UBLAS_INLINE
Chris@16 2411 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2412 typename self_type::
Chris@16 2413 #endif
Chris@16 2414 const_iterator1 begin () const {
Chris@16 2415 const self_type &m = (*this) ();
Chris@16 2416 return m.find1 (1, 0, index2 ());
Chris@16 2417 }
Chris@16 2418 BOOST_UBLAS_INLINE
Chris@16 2419 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2420 typename self_type::
Chris@16 2421 #endif
Chris@101 2422 const_iterator1 cbegin () const {
Chris@101 2423 return begin ();
Chris@101 2424 }
Chris@101 2425 BOOST_UBLAS_INLINE
Chris@101 2426 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 2427 typename self_type::
Chris@101 2428 #endif
Chris@16 2429 const_iterator1 end () const {
Chris@16 2430 const self_type &m = (*this) ();
Chris@16 2431 return m.find1 (1, m.size1 (), index2 ());
Chris@16 2432 }
Chris@16 2433 BOOST_UBLAS_INLINE
Chris@16 2434 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2435 typename self_type::
Chris@16 2436 #endif
Chris@101 2437 const_iterator1 cend () const {
Chris@101 2438 return end ();
Chris@101 2439 }
Chris@101 2440 BOOST_UBLAS_INLINE
Chris@101 2441 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 2442 typename self_type::
Chris@101 2443 #endif
Chris@16 2444 const_reverse_iterator1 rbegin () const {
Chris@16 2445 return const_reverse_iterator1 (end ());
Chris@16 2446 }
Chris@16 2447 BOOST_UBLAS_INLINE
Chris@16 2448 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2449 typename self_type::
Chris@16 2450 #endif
Chris@101 2451 const_reverse_iterator1 crbegin () const {
Chris@101 2452 return rbegin ();
Chris@101 2453 }
Chris@101 2454 BOOST_UBLAS_INLINE
Chris@101 2455 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 2456 typename self_type::
Chris@101 2457 #endif
Chris@16 2458 const_reverse_iterator1 rend () const {
Chris@16 2459 return const_reverse_iterator1 (begin ());
Chris@16 2460 }
Chris@101 2461 BOOST_UBLAS_INLINE
Chris@101 2462 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 2463 typename self_type::
Chris@101 2464 #endif
Chris@101 2465 const_reverse_iterator1 crend () const {
Chris@101 2466 return rend ();
Chris@101 2467 }
Chris@16 2468 #endif
Chris@16 2469
Chris@16 2470 // Indices
Chris@16 2471 BOOST_UBLAS_INLINE
Chris@16 2472 size_type index1 () const {
Chris@16 2473 if (rank_ == 1) {
Chris@16 2474 BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
Chris@16 2475 return layout_type::index_M ((*itv_).first, (*it_).first);
Chris@16 2476 } else {
Chris@16 2477 return i_;
Chris@16 2478 }
Chris@16 2479 }
Chris@16 2480 BOOST_UBLAS_INLINE
Chris@16 2481 size_type index2 () const {
Chris@16 2482 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
Chris@16 2483 if (rank_ == 1) {
Chris@16 2484 BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
Chris@16 2485 return layout_type::index_m ((*itv_).first, (*it_).first);
Chris@16 2486 } else {
Chris@16 2487 return j_;
Chris@16 2488 }
Chris@16 2489 }
Chris@16 2490
Chris@16 2491 // Assignment
Chris@16 2492 BOOST_UBLAS_INLINE
Chris@16 2493 const_iterator2 &operator = (const const_iterator2 &it) {
Chris@16 2494 container_const_reference<self_type>::assign (&it ());
Chris@16 2495 rank_ = it.rank_;
Chris@16 2496 i_ = it.i_;
Chris@16 2497 j_ = it.j_;
Chris@16 2498 itv_ = it.itv_;
Chris@16 2499 it_ = it.it_;
Chris@16 2500 return *this;
Chris@16 2501 }
Chris@16 2502
Chris@16 2503 // Comparison
Chris@16 2504 BOOST_UBLAS_INLINE
Chris@16 2505 bool operator == (const const_iterator2 &it) const {
Chris@16 2506 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 2507 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 2508 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 2509 return it_ == it.it_;
Chris@16 2510 } else {
Chris@16 2511 return i_ == it.i_ && j_ == it.j_;
Chris@16 2512 }
Chris@16 2513 }
Chris@16 2514
Chris@16 2515 private:
Chris@16 2516 int rank_;
Chris@16 2517 size_type i_;
Chris@16 2518 size_type j_;
Chris@16 2519 vector_const_subiterator_type itv_;
Chris@16 2520 const_subiterator_type it_;
Chris@16 2521 };
Chris@16 2522
Chris@16 2523 BOOST_UBLAS_INLINE
Chris@16 2524 const_iterator2 begin2 () const {
Chris@16 2525 return find2 (0, 0, 0);
Chris@16 2526 }
Chris@16 2527 BOOST_UBLAS_INLINE
Chris@101 2528 const_iterator2 cbegin2 () const {
Chris@101 2529 return begin2 ();
Chris@101 2530 }
Chris@101 2531 BOOST_UBLAS_INLINE
Chris@16 2532 const_iterator2 end2 () const {
Chris@16 2533 return find2 (0, 0, size2_);
Chris@16 2534 }
Chris@101 2535 BOOST_UBLAS_INLINE
Chris@101 2536 const_iterator2 cend2 () const {
Chris@101 2537 return end2 ();
Chris@101 2538 }
Chris@16 2539
Chris@16 2540 class iterator2:
Chris@16 2541 public container_reference<mapped_vector_of_mapped_vector>,
Chris@16 2542 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 2543 iterator2, value_type> {
Chris@16 2544 public:
Chris@16 2545 typedef typename mapped_vector_of_mapped_vector::value_type value_type;
Chris@16 2546 typedef typename mapped_vector_of_mapped_vector::difference_type difference_type;
Chris@16 2547 typedef typename mapped_vector_of_mapped_vector::true_reference reference;
Chris@16 2548 typedef typename mapped_vector_of_mapped_vector::pointer pointer;
Chris@16 2549
Chris@16 2550 typedef iterator1 dual_iterator_type;
Chris@16 2551 typedef reverse_iterator1 dual_reverse_iterator_type;
Chris@16 2552
Chris@16 2553 // Construction and destruction
Chris@16 2554 BOOST_UBLAS_INLINE
Chris@16 2555 iterator2 ():
Chris@16 2556 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
Chris@16 2557 BOOST_UBLAS_INLINE
Chris@16 2558 iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
Chris@16 2559 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
Chris@16 2560
Chris@16 2561 // Arithmetic
Chris@16 2562 BOOST_UBLAS_INLINE
Chris@16 2563 iterator2 &operator ++ () {
Chris@16 2564 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 2565 ++ it_;
Chris@16 2566 else {
Chris@16 2567 self_type &m = (*this) ();
Chris@16 2568 if (rank_ == 0) {
Chris@16 2569 ++ itv_;
Chris@16 2570 j_ = itv_->first;
Chris@16 2571 } else {
Chris@16 2572 j_ = index2 () + 1;
Chris@16 2573 }
Chris@16 2574 if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
Chris@16 2575 *this = m.find2 (rank_, i_, j_, 1);
Chris@16 2576 else if (rank_ == 1) {
Chris@16 2577 it_ = (*itv_).second.begin ();
Chris@16 2578 if (it_ == (*itv_).second.end () || index1 () != i_)
Chris@16 2579 *this = m.find2 (rank_, i_, j_, 1);
Chris@16 2580 }
Chris@16 2581 }
Chris@16 2582 return *this;
Chris@16 2583 }
Chris@16 2584 BOOST_UBLAS_INLINE
Chris@16 2585 iterator2 &operator -- () {
Chris@16 2586 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 2587 -- it_;
Chris@16 2588 else {
Chris@16 2589 self_type &m = (*this) ();
Chris@16 2590 if (rank_ == 0) {
Chris@16 2591 -- itv_;
Chris@16 2592 j_ = itv_->first;
Chris@16 2593 } else {
Chris@16 2594 j_ = index2 () - 1;
Chris@16 2595 }
Chris@16 2596 // FIXME: this expression should never become true!
Chris@16 2597 if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
Chris@16 2598 *this = m.find2 (rank_, i_, j_, -1);
Chris@16 2599 else if (rank_ == 1) {
Chris@16 2600 it_ = (*itv_).second.begin ();
Chris@16 2601 if (it_ == (*itv_).second.end () || index1 () != i_)
Chris@16 2602 *this = m.find2 (rank_, i_, j_, -1);
Chris@16 2603 }
Chris@16 2604 }
Chris@16 2605 return *this;
Chris@16 2606 }
Chris@16 2607
Chris@16 2608 // Dereference
Chris@16 2609 BOOST_UBLAS_INLINE
Chris@16 2610 reference operator * () const {
Chris@16 2611 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 2612 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 2613 if (rank_ == 1) {
Chris@16 2614 return (*it_).second;
Chris@16 2615 } else {
Chris@16 2616 return (*this) ().at_element (i_, j_);
Chris@16 2617 }
Chris@16 2618 }
Chris@16 2619
Chris@16 2620 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 2621 BOOST_UBLAS_INLINE
Chris@16 2622 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2623 typename self_type::
Chris@16 2624 #endif
Chris@16 2625 iterator1 begin () const {
Chris@16 2626 self_type &m = (*this) ();
Chris@16 2627 return m.find1 (1, 0, index2 ());
Chris@16 2628 }
Chris@16 2629 BOOST_UBLAS_INLINE
Chris@16 2630 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2631 typename self_type::
Chris@16 2632 #endif
Chris@16 2633 iterator1 end () const {
Chris@16 2634 self_type &m = (*this) ();
Chris@16 2635 return m.find1 (1, m.size1 (), index2 ());
Chris@16 2636 }
Chris@16 2637 BOOST_UBLAS_INLINE
Chris@16 2638 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2639 typename self_type::
Chris@16 2640 #endif
Chris@16 2641 reverse_iterator1 rbegin () const {
Chris@16 2642 return reverse_iterator1 (end ());
Chris@16 2643 }
Chris@16 2644 BOOST_UBLAS_INLINE
Chris@16 2645 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 2646 typename self_type::
Chris@16 2647 #endif
Chris@16 2648 reverse_iterator1 rend () const {
Chris@16 2649 return reverse_iterator1 (begin ());
Chris@16 2650 }
Chris@16 2651 #endif
Chris@16 2652
Chris@16 2653 // Indices
Chris@16 2654 BOOST_UBLAS_INLINE
Chris@16 2655 size_type index1 () const {
Chris@16 2656 if (rank_ == 1) {
Chris@16 2657 BOOST_UBLAS_CHECK (layout_type::index_M ((*itv_).first, (*it_).first) < (*this) ().size1 (), bad_index ());
Chris@16 2658 return layout_type::index_M ((*itv_).first, (*it_).first);
Chris@16 2659 } else {
Chris@16 2660 return i_;
Chris@16 2661 }
Chris@16 2662 }
Chris@16 2663 BOOST_UBLAS_INLINE
Chris@16 2664 size_type index2 () const {
Chris@16 2665 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
Chris@16 2666 if (rank_ == 1) {
Chris@16 2667 BOOST_UBLAS_CHECK (layout_type::index_m ((*itv_).first, (*it_).first) < (*this) ().size2 (), bad_index ());
Chris@16 2668 return layout_type::index_m ((*itv_).first, (*it_).first);
Chris@16 2669 } else {
Chris@16 2670 return j_;
Chris@16 2671 }
Chris@16 2672 }
Chris@16 2673
Chris@16 2674 // Assignment
Chris@16 2675 BOOST_UBLAS_INLINE
Chris@16 2676 iterator2 &operator = (const iterator2 &it) {
Chris@16 2677 container_reference<self_type>::assign (&it ());
Chris@16 2678 rank_ = it.rank_;
Chris@16 2679 i_ = it.i_;
Chris@16 2680 j_ = it.j_;
Chris@16 2681 itv_ = it.itv_;
Chris@16 2682 it_ = it.it_;
Chris@16 2683 return *this;
Chris@16 2684 }
Chris@16 2685
Chris@16 2686 // Comparison
Chris@16 2687 BOOST_UBLAS_INLINE
Chris@16 2688 bool operator == (const iterator2 &it) const {
Chris@16 2689 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 2690 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 2691 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 2692 return it_ == it.it_;
Chris@16 2693 } else {
Chris@16 2694 return i_ == it.i_ && j_ == it.j_;
Chris@16 2695 }
Chris@16 2696 }
Chris@16 2697
Chris@16 2698 private:
Chris@16 2699 int rank_;
Chris@16 2700 size_type i_;
Chris@16 2701 size_type j_;
Chris@16 2702 vector_subiterator_type itv_;
Chris@16 2703 subiterator_type it_;
Chris@16 2704
Chris@16 2705 friend class const_iterator2;
Chris@16 2706 };
Chris@16 2707
Chris@16 2708 BOOST_UBLAS_INLINE
Chris@16 2709 iterator2 begin2 () {
Chris@16 2710 return find2 (0, 0, 0);
Chris@16 2711 }
Chris@16 2712 BOOST_UBLAS_INLINE
Chris@16 2713 iterator2 end2 () {
Chris@16 2714 return find2 (0, 0, size2_);
Chris@16 2715 }
Chris@16 2716
Chris@16 2717 // Reverse iterators
Chris@16 2718
Chris@16 2719 BOOST_UBLAS_INLINE
Chris@16 2720 const_reverse_iterator1 rbegin1 () const {
Chris@16 2721 return const_reverse_iterator1 (end1 ());
Chris@16 2722 }
Chris@16 2723 BOOST_UBLAS_INLINE
Chris@101 2724 const_reverse_iterator1 crbegin1 () const {
Chris@101 2725 return rbegin1 ();
Chris@101 2726 }
Chris@101 2727 BOOST_UBLAS_INLINE
Chris@16 2728 const_reverse_iterator1 rend1 () const {
Chris@16 2729 return const_reverse_iterator1 (begin1 ());
Chris@16 2730 }
Chris@101 2731 BOOST_UBLAS_INLINE
Chris@101 2732 const_reverse_iterator1 crend1 () const {
Chris@101 2733 return rend1 ();
Chris@101 2734 }
Chris@16 2735
Chris@16 2736 BOOST_UBLAS_INLINE
Chris@16 2737 reverse_iterator1 rbegin1 () {
Chris@16 2738 return reverse_iterator1 (end1 ());
Chris@16 2739 }
Chris@16 2740 BOOST_UBLAS_INLINE
Chris@16 2741 reverse_iterator1 rend1 () {
Chris@16 2742 return reverse_iterator1 (begin1 ());
Chris@16 2743 }
Chris@16 2744
Chris@16 2745 BOOST_UBLAS_INLINE
Chris@16 2746 const_reverse_iterator2 rbegin2 () const {
Chris@16 2747 return const_reverse_iterator2 (end2 ());
Chris@16 2748 }
Chris@16 2749 BOOST_UBLAS_INLINE
Chris@101 2750 const_reverse_iterator2 crbegin2 () const {
Chris@101 2751 return rbegin2 ();
Chris@101 2752 }
Chris@101 2753 BOOST_UBLAS_INLINE
Chris@16 2754 const_reverse_iterator2 rend2 () const {
Chris@16 2755 return const_reverse_iterator2 (begin2 ());
Chris@16 2756 }
Chris@101 2757 BOOST_UBLAS_INLINE
Chris@101 2758 const_reverse_iterator2 crend2 () const {
Chris@101 2759 return rend2 ();
Chris@101 2760 }
Chris@16 2761
Chris@16 2762 BOOST_UBLAS_INLINE
Chris@16 2763 reverse_iterator2 rbegin2 () {
Chris@16 2764 return reverse_iterator2 (end2 ());
Chris@16 2765 }
Chris@16 2766 BOOST_UBLAS_INLINE
Chris@16 2767 reverse_iterator2 rend2 () {
Chris@16 2768 return reverse_iterator2 (begin2 ());
Chris@16 2769 }
Chris@16 2770
Chris@16 2771 // Serialization
Chris@16 2772 template<class Archive>
Chris@16 2773 void serialize(Archive & ar, const unsigned int /* file_version */){
Chris@16 2774 serialization::collection_size_type s1 (size1_);
Chris@16 2775 serialization::collection_size_type s2 (size2_);
Chris@16 2776 ar & serialization::make_nvp("size1",s1);
Chris@16 2777 ar & serialization::make_nvp("size2",s2);
Chris@16 2778 if (Archive::is_loading::value) {
Chris@16 2779 size1_ = s1;
Chris@16 2780 size2_ = s2;
Chris@16 2781 }
Chris@16 2782 ar & serialization::make_nvp("data", data_);
Chris@16 2783 }
Chris@16 2784
Chris@16 2785 private:
Chris@16 2786 size_type size1_;
Chris@16 2787 size_type size2_;
Chris@16 2788 array_type data_;
Chris@16 2789 static const value_type zero_;
Chris@16 2790 };
Chris@16 2791
Chris@16 2792 template<class T, class L, class A>
Chris@16 2793 const typename mapped_vector_of_mapped_vector<T, L, A>::value_type mapped_vector_of_mapped_vector<T, L, A>::zero_ = value_type/*zero*/();
Chris@16 2794
Chris@16 2795
Chris@16 2796 // Comperssed array based sparse matrix class
Chris@16 2797 // Thanks to Kresimir Fresl for extending this to cover different index bases.
Chris@16 2798 template<class T, class L, std::size_t IB, class IA, class TA>
Chris@16 2799 class compressed_matrix:
Chris@16 2800 public matrix_container<compressed_matrix<T, L, IB, IA, TA> > {
Chris@16 2801
Chris@16 2802 typedef T &true_reference;
Chris@16 2803 typedef T *pointer;
Chris@16 2804 typedef const T *const_pointer;
Chris@16 2805 typedef L layout_type;
Chris@16 2806 typedef compressed_matrix<T, L, IB, IA, TA> self_type;
Chris@16 2807 public:
Chris@16 2808 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
Chris@16 2809 using matrix_container<self_type>::operator ();
Chris@16 2810 #endif
Chris@16 2811 // ISSUE require type consistency check
Chris@16 2812 // is_convertable (IA::size_type, TA::size_type)
Chris@16 2813 typedef typename IA::value_type size_type;
Chris@16 2814 // size_type for the data arrays.
Chris@16 2815 typedef typename IA::size_type array_size_type;
Chris@16 2816 // FIXME difference type for sparse storage iterators should it be in the container?
Chris@16 2817 typedef typename IA::difference_type difference_type;
Chris@16 2818 typedef T value_type;
Chris@16 2819 typedef const T &const_reference;
Chris@16 2820 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
Chris@16 2821 typedef T &reference;
Chris@16 2822 #else
Chris@16 2823 typedef sparse_matrix_element<self_type> reference;
Chris@16 2824 #endif
Chris@16 2825 typedef IA index_array_type;
Chris@16 2826 typedef TA value_array_type;
Chris@16 2827 typedef const matrix_reference<const self_type> const_closure_type;
Chris@16 2828 typedef matrix_reference<self_type> closure_type;
Chris@16 2829 typedef compressed_vector<T, IB, IA, TA> vector_temporary_type;
Chris@16 2830 typedef self_type matrix_temporary_type;
Chris@16 2831 typedef sparse_tag storage_category;
Chris@16 2832 typedef typename L::orientation_category orientation_category;
Chris@16 2833
Chris@16 2834 // Construction and destruction
Chris@16 2835 BOOST_UBLAS_INLINE
Chris@16 2836 compressed_matrix ():
Chris@16 2837 matrix_container<self_type> (),
Chris@16 2838 size1_ (0), size2_ (0), capacity_ (restrict_capacity (0)),
Chris@16 2839 filled1_ (1), filled2_ (0),
Chris@16 2840 index1_data_ (layout_type::size_M (size1_, size2_) + 1), index2_data_ (capacity_), value_data_ (capacity_) {
Chris@16 2841 index1_data_ [filled1_ - 1] = k_based (filled2_);
Chris@16 2842 storage_invariants ();
Chris@16 2843 }
Chris@16 2844 BOOST_UBLAS_INLINE
Chris@16 2845 compressed_matrix (size_type size1, size_type size2, size_type non_zeros = 0):
Chris@16 2846 matrix_container<self_type> (),
Chris@16 2847 size1_ (size1), size2_ (size2), capacity_ (restrict_capacity (non_zeros)),
Chris@16 2848 filled1_ (1), filled2_ (0),
Chris@16 2849 index1_data_ (layout_type::size_M (size1_, size2_) + 1), index2_data_ (capacity_), value_data_ (capacity_) {
Chris@16 2850 index1_data_ [filled1_ - 1] = k_based (filled2_);
Chris@16 2851 storage_invariants ();
Chris@16 2852 }
Chris@16 2853 BOOST_UBLAS_INLINE
Chris@16 2854 compressed_matrix (const compressed_matrix &m):
Chris@16 2855 matrix_container<self_type> (),
Chris@16 2856 size1_ (m.size1_), size2_ (m.size2_), capacity_ (m.capacity_),
Chris@16 2857 filled1_ (m.filled1_), filled2_ (m.filled2_),
Chris@16 2858 index1_data_ (m.index1_data_), index2_data_ (m.index2_data_), value_data_ (m.value_data_) {
Chris@16 2859 storage_invariants ();
Chris@16 2860 }
Chris@16 2861
Chris@16 2862 BOOST_UBLAS_INLINE
Chris@16 2863 compressed_matrix (const coordinate_matrix<T, L, IB, IA, TA> &m):
Chris@16 2864 matrix_container<self_type> (),
Chris@16 2865 size1_ (m.size1()), size2_ (m.size2()),
Chris@16 2866 index1_data_ (layout_type::size_M (size1_, size2_) + 1)
Chris@16 2867 {
Chris@16 2868 m.sort();
Chris@16 2869 reserve(m.nnz(), false);
Chris@16 2870 filled2_ = m.nnz();
Chris@16 2871 const_subiterator_type i_start = m.index1_data().begin();
Chris@16 2872 const_subiterator_type i_end = (i_start + filled2_);
Chris@16 2873 const_subiterator_type i = i_start;
Chris@16 2874 size_type r = 1;
Chris@16 2875 for (; (r < layout_type::size_M (size1_, size2_)) && (i != i_end); ++r) {
Chris@16 2876 i = std::lower_bound(i, i_end, r);
Chris@16 2877 index1_data_[r] = k_based( i - i_start );
Chris@16 2878 }
Chris@16 2879 filled1_ = r + 1;
Chris@16 2880 std::copy( m.index2_data().begin(), m.index2_data().begin() + filled2_, index2_data_.begin());
Chris@16 2881 std::copy( m.value_data().begin(), m.value_data().begin() + filled2_, value_data_.begin());
Chris@16 2882 index1_data_ [filled1_ - 1] = k_based(filled2_);
Chris@16 2883 storage_invariants ();
Chris@16 2884 }
Chris@16 2885
Chris@16 2886 template<class AE>
Chris@16 2887 BOOST_UBLAS_INLINE
Chris@16 2888 compressed_matrix (const matrix_expression<AE> &ae, size_type non_zeros = 0):
Chris@16 2889 matrix_container<self_type> (),
Chris@16 2890 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), capacity_ (restrict_capacity (non_zeros)),
Chris@16 2891 filled1_ (1), filled2_ (0),
Chris@16 2892 index1_data_ (layout_type::size_M (ae ().size1 (), ae ().size2 ()) + 1),
Chris@16 2893 index2_data_ (capacity_), value_data_ (capacity_) {
Chris@16 2894 index1_data_ [filled1_ - 1] = k_based (filled2_);
Chris@16 2895 storage_invariants ();
Chris@16 2896 matrix_assign<scalar_assign> (*this, ae);
Chris@16 2897 }
Chris@16 2898
Chris@16 2899 // Accessors
Chris@16 2900 BOOST_UBLAS_INLINE
Chris@16 2901 size_type size1 () const {
Chris@16 2902 return size1_;
Chris@16 2903 }
Chris@16 2904 BOOST_UBLAS_INLINE
Chris@16 2905 size_type size2 () const {
Chris@16 2906 return size2_;
Chris@16 2907 }
Chris@16 2908 BOOST_UBLAS_INLINE
Chris@16 2909 size_type nnz_capacity () const {
Chris@16 2910 return capacity_;
Chris@16 2911 }
Chris@16 2912 BOOST_UBLAS_INLINE
Chris@16 2913 size_type nnz () const {
Chris@16 2914 return filled2_;
Chris@16 2915 }
Chris@16 2916
Chris@16 2917 // Storage accessors
Chris@16 2918 BOOST_UBLAS_INLINE
Chris@16 2919 static size_type index_base () {
Chris@16 2920 return IB;
Chris@16 2921 }
Chris@16 2922 BOOST_UBLAS_INLINE
Chris@16 2923 array_size_type filled1 () const {
Chris@16 2924 return filled1_;
Chris@16 2925 }
Chris@16 2926 BOOST_UBLAS_INLINE
Chris@16 2927 array_size_type filled2 () const {
Chris@16 2928 return filled2_;
Chris@16 2929 }
Chris@16 2930 BOOST_UBLAS_INLINE
Chris@16 2931 const index_array_type &index1_data () const {
Chris@16 2932 return index1_data_;
Chris@16 2933 }
Chris@16 2934 BOOST_UBLAS_INLINE
Chris@16 2935 const index_array_type &index2_data () const {
Chris@16 2936 return index2_data_;
Chris@16 2937 }
Chris@16 2938 BOOST_UBLAS_INLINE
Chris@16 2939 const value_array_type &value_data () const {
Chris@16 2940 return value_data_;
Chris@16 2941 }
Chris@16 2942 BOOST_UBLAS_INLINE
Chris@16 2943 void set_filled (const array_size_type& filled1, const array_size_type& filled2) {
Chris@16 2944 filled1_ = filled1;
Chris@16 2945 filled2_ = filled2;
Chris@16 2946 storage_invariants ();
Chris@16 2947 }
Chris@16 2948 BOOST_UBLAS_INLINE
Chris@16 2949 index_array_type &index1_data () {
Chris@16 2950 return index1_data_;
Chris@16 2951 }
Chris@16 2952 BOOST_UBLAS_INLINE
Chris@16 2953 index_array_type &index2_data () {
Chris@16 2954 return index2_data_;
Chris@16 2955 }
Chris@16 2956 BOOST_UBLAS_INLINE
Chris@16 2957 value_array_type &value_data () {
Chris@16 2958 return value_data_;
Chris@16 2959 }
Chris@16 2960 BOOST_UBLAS_INLINE
Chris@16 2961 void complete_index1_data () {
Chris@16 2962 while (filled1_ <= layout_type::size_M (size1_, size2_)) {
Chris@16 2963 this->index1_data_ [filled1_] = k_based (filled2_);
Chris@16 2964 ++ this->filled1_;
Chris@16 2965 }
Chris@16 2966 }
Chris@16 2967
Chris@16 2968 // Resizing
Chris@16 2969 private:
Chris@16 2970 BOOST_UBLAS_INLINE
Chris@16 2971 size_type restrict_capacity (size_type non_zeros) const {
Chris@16 2972 non_zeros = (std::max) (non_zeros, (std::min) (size1_, size2_));
Chris@16 2973 // Guarding against overflow - Thanks to Alexei Novakov for the hint.
Chris@16 2974 // non_zeros = (std::min) (non_zeros, size1_ * size2_);
Chris@16 2975 if (size1_ > 0 && non_zeros / size1_ >= size2_)
Chris@16 2976 non_zeros = size1_ * size2_;
Chris@16 2977 return non_zeros;
Chris@16 2978 }
Chris@16 2979 public:
Chris@16 2980 BOOST_UBLAS_INLINE
Chris@16 2981 void resize (size_type size1, size_type size2, bool preserve = true) {
Chris@16 2982 // FIXME preserve unimplemented
Chris@16 2983 BOOST_UBLAS_CHECK (!preserve, internal_logic ());
Chris@16 2984 size1_ = size1;
Chris@16 2985 size2_ = size2;
Chris@16 2986 capacity_ = restrict_capacity (capacity_);
Chris@16 2987 filled1_ = 1;
Chris@16 2988 filled2_ = 0;
Chris@16 2989 index1_data_.resize (layout_type::size_M (size1_, size2_) + 1);
Chris@16 2990 index2_data_.resize (capacity_);
Chris@16 2991 value_data_.resize (capacity_);
Chris@16 2992 index1_data_ [filled1_ - 1] = k_based (filled2_);
Chris@16 2993 storage_invariants ();
Chris@16 2994 }
Chris@16 2995
Chris@16 2996 // Reserving
Chris@16 2997 BOOST_UBLAS_INLINE
Chris@16 2998 void reserve (size_type non_zeros, bool preserve = true) {
Chris@16 2999 capacity_ = restrict_capacity (non_zeros);
Chris@16 3000 if (preserve) {
Chris@16 3001 index2_data_.resize (capacity_, size_type ());
Chris@16 3002 value_data_.resize (capacity_, value_type ());
Chris@16 3003 filled2_ = (std::min) (capacity_, filled2_);
Chris@16 3004 }
Chris@16 3005 else {
Chris@16 3006 index2_data_.resize (capacity_);
Chris@16 3007 value_data_.resize (capacity_);
Chris@16 3008 filled1_ = 1;
Chris@16 3009 filled2_ = 0;
Chris@16 3010 index1_data_ [filled1_ - 1] = k_based (filled2_);
Chris@16 3011 }
Chris@16 3012 storage_invariants ();
Chris@16 3013 }
Chris@16 3014
Chris@16 3015 // Element support
Chris@16 3016 BOOST_UBLAS_INLINE
Chris@16 3017 pointer find_element (size_type i, size_type j) {
Chris@16 3018 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
Chris@16 3019 }
Chris@16 3020 BOOST_UBLAS_INLINE
Chris@16 3021 const_pointer find_element (size_type i, size_type j) const {
Chris@16 3022 size_type element1 (layout_type::index_M (i, j));
Chris@16 3023 size_type element2 (layout_type::index_m (i, j));
Chris@16 3024 if (filled1_ <= element1 + 1)
Chris@16 3025 return 0;
Chris@16 3026 vector_const_subiterator_type itv (index1_data_.begin () + element1);
Chris@16 3027 const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
Chris@16 3028 const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
Chris@16 3029 const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
Chris@16 3030 if (it == it_end || *it != k_based (element2))
Chris@16 3031 return 0;
Chris@16 3032 return &value_data_ [it - index2_data_.begin ()];
Chris@16 3033 }
Chris@16 3034
Chris@16 3035 // Element access
Chris@16 3036 BOOST_UBLAS_INLINE
Chris@16 3037 const_reference operator () (size_type i, size_type j) const {
Chris@16 3038 const_pointer p = find_element (i, j);
Chris@16 3039 if (p)
Chris@16 3040 return *p;
Chris@16 3041 else
Chris@16 3042 return zero_;
Chris@16 3043 }
Chris@16 3044 BOOST_UBLAS_INLINE
Chris@16 3045 reference operator () (size_type i, size_type j) {
Chris@16 3046 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
Chris@16 3047 size_type element1 (layout_type::index_M (i, j));
Chris@16 3048 size_type element2 (layout_type::index_m (i, j));
Chris@16 3049 if (filled1_ <= element1 + 1)
Chris@16 3050 return insert_element (i, j, value_type/*zero*/());
Chris@16 3051 pointer p = find_element (i, j);
Chris@16 3052 if (p)
Chris@16 3053 return *p;
Chris@16 3054 else
Chris@16 3055 return insert_element (i, j, value_type/*zero*/());
Chris@16 3056 #else
Chris@16 3057 return reference (*this, i, j);
Chris@16 3058 #endif
Chris@16 3059 }
Chris@16 3060
Chris@16 3061 // Element assignment
Chris@16 3062 BOOST_UBLAS_INLINE
Chris@16 3063 true_reference insert_element (size_type i, size_type j, const_reference t) {
Chris@16 3064 BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
Chris@16 3065 if (filled2_ >= capacity_)
Chris@16 3066 reserve (2 * filled2_, true);
Chris@16 3067 BOOST_UBLAS_CHECK (filled2_ < capacity_, internal_logic ());
Chris@16 3068 size_type element1 = layout_type::index_M (i, j);
Chris@16 3069 size_type element2 = layout_type::index_m (i, j);
Chris@16 3070 while (filled1_ <= element1 + 1) {
Chris@16 3071 index1_data_ [filled1_] = k_based (filled2_);
Chris@16 3072 ++ filled1_;
Chris@16 3073 }
Chris@16 3074 vector_subiterator_type itv (index1_data_.begin () + element1);
Chris@16 3075 subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
Chris@16 3076 subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
Chris@16 3077 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
Chris@16 3078 typename std::iterator_traits<subiterator_type>::difference_type n = it - index2_data_.begin ();
Chris@16 3079 BOOST_UBLAS_CHECK (it == it_end || *it != k_based (element2), internal_logic ()); // duplicate bound by lower_bound
Chris@16 3080 ++ filled2_;
Chris@16 3081 it = index2_data_.begin () + n;
Chris@16 3082 std::copy_backward (it, index2_data_.begin () + filled2_ - 1, index2_data_.begin () + filled2_);
Chris@16 3083 *it = k_based (element2);
Chris@16 3084 typename value_array_type::iterator itt (value_data_.begin () + n);
Chris@16 3085 std::copy_backward (itt, value_data_.begin () + filled2_ - 1, value_data_.begin () + filled2_);
Chris@16 3086 *itt = t;
Chris@16 3087 while (element1 + 1 < filled1_) {
Chris@16 3088 ++ index1_data_ [element1 + 1];
Chris@16 3089 ++ element1;
Chris@16 3090 }
Chris@16 3091 storage_invariants ();
Chris@16 3092 return *itt;
Chris@16 3093 }
Chris@16 3094 BOOST_UBLAS_INLINE
Chris@16 3095 void erase_element (size_type i, size_type j) {
Chris@16 3096 size_type element1 = layout_type::index_M (i, j);
Chris@16 3097 size_type element2 = layout_type::index_m (i, j);
Chris@16 3098 if (element1 + 1 >= filled1_)
Chris@16 3099 return;
Chris@16 3100 vector_subiterator_type itv (index1_data_.begin () + element1);
Chris@16 3101 subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
Chris@16 3102 subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
Chris@16 3103 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
Chris@16 3104 if (it != it_end && *it == k_based (element2)) {
Chris@16 3105 typename std::iterator_traits<subiterator_type>::difference_type n = it - index2_data_.begin ();
Chris@16 3106 std::copy (it + 1, index2_data_.begin () + filled2_, it);
Chris@16 3107 typename value_array_type::iterator itt (value_data_.begin () + n);
Chris@16 3108 std::copy (itt + 1, value_data_.begin () + filled2_, itt);
Chris@16 3109 -- filled2_;
Chris@16 3110 while (index1_data_ [filled1_ - 2] > k_based (filled2_)) {
Chris@16 3111 index1_data_ [filled1_ - 1] = 0;
Chris@16 3112 -- filled1_;
Chris@16 3113 }
Chris@16 3114 while (element1 + 1 < filled1_) {
Chris@16 3115 -- index1_data_ [element1 + 1];
Chris@16 3116 ++ element1;
Chris@16 3117 }
Chris@16 3118 }
Chris@16 3119 storage_invariants ();
Chris@16 3120 }
Chris@16 3121
Chris@16 3122 // Zeroing
Chris@16 3123 BOOST_UBLAS_INLINE
Chris@16 3124 void clear () {
Chris@16 3125 filled1_ = 1;
Chris@16 3126 filled2_ = 0;
Chris@16 3127 index1_data_ [filled1_ - 1] = k_based (filled2_);
Chris@16 3128 storage_invariants ();
Chris@16 3129 }
Chris@16 3130
Chris@16 3131 // Assignment
Chris@16 3132 BOOST_UBLAS_INLINE
Chris@16 3133 compressed_matrix &operator = (const compressed_matrix &m) {
Chris@16 3134 if (this != &m) {
Chris@16 3135 size1_ = m.size1_;
Chris@16 3136 size2_ = m.size2_;
Chris@16 3137 capacity_ = m.capacity_;
Chris@16 3138 filled1_ = m.filled1_;
Chris@16 3139 filled2_ = m.filled2_;
Chris@16 3140 index1_data_ = m.index1_data_;
Chris@16 3141 index2_data_ = m.index2_data_;
Chris@16 3142 value_data_ = m.value_data_;
Chris@16 3143 }
Chris@16 3144 storage_invariants ();
Chris@16 3145 return *this;
Chris@16 3146 }
Chris@16 3147 template<class C> // Container assignment without temporary
Chris@16 3148 BOOST_UBLAS_INLINE
Chris@16 3149 compressed_matrix &operator = (const matrix_container<C> &m) {
Chris@16 3150 resize (m ().size1 (), m ().size2 (), false);
Chris@16 3151 assign (m);
Chris@16 3152 return *this;
Chris@16 3153 }
Chris@16 3154 BOOST_UBLAS_INLINE
Chris@16 3155 compressed_matrix &assign_temporary (compressed_matrix &m) {
Chris@16 3156 swap (m);
Chris@16 3157 return *this;
Chris@16 3158 }
Chris@16 3159 template<class AE>
Chris@16 3160 BOOST_UBLAS_INLINE
Chris@16 3161 compressed_matrix &operator = (const matrix_expression<AE> &ae) {
Chris@16 3162 self_type temporary (ae, capacity_);
Chris@16 3163 return assign_temporary (temporary);
Chris@16 3164 }
Chris@16 3165 template<class AE>
Chris@16 3166 BOOST_UBLAS_INLINE
Chris@16 3167 compressed_matrix &assign (const matrix_expression<AE> &ae) {
Chris@16 3168 matrix_assign<scalar_assign> (*this, ae);
Chris@16 3169 return *this;
Chris@16 3170 }
Chris@16 3171 template<class AE>
Chris@16 3172 BOOST_UBLAS_INLINE
Chris@16 3173 compressed_matrix& operator += (const matrix_expression<AE> &ae) {
Chris@16 3174 self_type temporary (*this + ae, capacity_);
Chris@16 3175 return assign_temporary (temporary);
Chris@16 3176 }
Chris@16 3177 template<class C> // Container assignment without temporary
Chris@16 3178 BOOST_UBLAS_INLINE
Chris@16 3179 compressed_matrix &operator += (const matrix_container<C> &m) {
Chris@16 3180 plus_assign (m);
Chris@16 3181 return *this;
Chris@16 3182 }
Chris@16 3183 template<class AE>
Chris@16 3184 BOOST_UBLAS_INLINE
Chris@16 3185 compressed_matrix &plus_assign (const matrix_expression<AE> &ae) {
Chris@16 3186 matrix_assign<scalar_plus_assign> (*this, ae);
Chris@16 3187 return *this;
Chris@16 3188 }
Chris@16 3189 template<class AE>
Chris@16 3190 BOOST_UBLAS_INLINE
Chris@16 3191 compressed_matrix& operator -= (const matrix_expression<AE> &ae) {
Chris@16 3192 self_type temporary (*this - ae, capacity_);
Chris@16 3193 return assign_temporary (temporary);
Chris@16 3194 }
Chris@16 3195 template<class C> // Container assignment without temporary
Chris@16 3196 BOOST_UBLAS_INLINE
Chris@16 3197 compressed_matrix &operator -= (const matrix_container<C> &m) {
Chris@16 3198 minus_assign (m);
Chris@16 3199 return *this;
Chris@16 3200 }
Chris@16 3201 template<class AE>
Chris@16 3202 BOOST_UBLAS_INLINE
Chris@16 3203 compressed_matrix &minus_assign (const matrix_expression<AE> &ae) {
Chris@16 3204 matrix_assign<scalar_minus_assign> (*this, ae);
Chris@16 3205 return *this;
Chris@16 3206 }
Chris@16 3207 template<class AT>
Chris@16 3208 BOOST_UBLAS_INLINE
Chris@16 3209 compressed_matrix& operator *= (const AT &at) {
Chris@16 3210 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
Chris@16 3211 return *this;
Chris@16 3212 }
Chris@16 3213 template<class AT>
Chris@16 3214 BOOST_UBLAS_INLINE
Chris@16 3215 compressed_matrix& operator /= (const AT &at) {
Chris@16 3216 matrix_assign_scalar<scalar_divides_assign> (*this, at);
Chris@16 3217 return *this;
Chris@16 3218 }
Chris@16 3219
Chris@16 3220 // Swapping
Chris@16 3221 BOOST_UBLAS_INLINE
Chris@16 3222 void swap (compressed_matrix &m) {
Chris@16 3223 if (this != &m) {
Chris@16 3224 std::swap (size1_, m.size1_);
Chris@16 3225 std::swap (size2_, m.size2_);
Chris@16 3226 std::swap (capacity_, m.capacity_);
Chris@16 3227 std::swap (filled1_, m.filled1_);
Chris@16 3228 std::swap (filled2_, m.filled2_);
Chris@16 3229 index1_data_.swap (m.index1_data_);
Chris@16 3230 index2_data_.swap (m.index2_data_);
Chris@16 3231 value_data_.swap (m.value_data_);
Chris@16 3232 }
Chris@16 3233 storage_invariants ();
Chris@16 3234 }
Chris@16 3235 BOOST_UBLAS_INLINE
Chris@16 3236 friend void swap (compressed_matrix &m1, compressed_matrix &m2) {
Chris@16 3237 m1.swap (m2);
Chris@16 3238 }
Chris@16 3239
Chris@16 3240 // Back element insertion and erasure
Chris@16 3241 BOOST_UBLAS_INLINE
Chris@16 3242 void push_back (size_type i, size_type j, const_reference t) {
Chris@16 3243 if (filled2_ >= capacity_)
Chris@16 3244 reserve (2 * filled2_, true);
Chris@16 3245 BOOST_UBLAS_CHECK (filled2_ < capacity_, internal_logic ());
Chris@16 3246 size_type element1 = layout_type::index_M (i, j);
Chris@16 3247 size_type element2 = layout_type::index_m (i, j);
Chris@16 3248 while (filled1_ < element1 + 2) {
Chris@16 3249 index1_data_ [filled1_] = k_based (filled2_);
Chris@16 3250 ++ filled1_;
Chris@16 3251 }
Chris@16 3252 // must maintain sort order
Chris@16 3253 BOOST_UBLAS_CHECK ((filled1_ == element1 + 2 &&
Chris@16 3254 (filled2_ == zero_based (index1_data_ [filled1_ - 2]) ||
Chris@16 3255 index2_data_ [filled2_ - 1] < k_based (element2))), external_logic ());
Chris@16 3256 ++ filled2_;
Chris@16 3257 index1_data_ [filled1_ - 1] = k_based (filled2_);
Chris@16 3258 index2_data_ [filled2_ - 1] = k_based (element2);
Chris@16 3259 value_data_ [filled2_ - 1] = t;
Chris@16 3260 storage_invariants ();
Chris@16 3261 }
Chris@16 3262 BOOST_UBLAS_INLINE
Chris@16 3263 void pop_back () {
Chris@16 3264 BOOST_UBLAS_CHECK (filled1_ > 0 && filled2_ > 0, external_logic ());
Chris@16 3265 -- filled2_;
Chris@16 3266 while (index1_data_ [filled1_ - 2] > k_based (filled2_)) {
Chris@16 3267 index1_data_ [filled1_ - 1] = 0;
Chris@16 3268 -- filled1_;
Chris@16 3269 }
Chris@16 3270 -- index1_data_ [filled1_ - 1];
Chris@16 3271 storage_invariants ();
Chris@16 3272 }
Chris@16 3273
Chris@16 3274 // Iterator types
Chris@16 3275 private:
Chris@16 3276 // Use index array iterator
Chris@16 3277 typedef typename IA::const_iterator vector_const_subiterator_type;
Chris@16 3278 typedef typename IA::iterator vector_subiterator_type;
Chris@16 3279 typedef typename IA::const_iterator const_subiterator_type;
Chris@16 3280 typedef typename IA::iterator subiterator_type;
Chris@16 3281
Chris@16 3282 BOOST_UBLAS_INLINE
Chris@16 3283 true_reference at_element (size_type i, size_type j) {
Chris@16 3284 pointer p = find_element (i, j);
Chris@16 3285 BOOST_UBLAS_CHECK (p, bad_index ());
Chris@16 3286 return *p;
Chris@16 3287 }
Chris@16 3288
Chris@16 3289 public:
Chris@16 3290 class const_iterator1;
Chris@16 3291 class iterator1;
Chris@16 3292 class const_iterator2;
Chris@16 3293 class iterator2;
Chris@16 3294 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
Chris@16 3295 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
Chris@16 3296 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
Chris@16 3297 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
Chris@16 3298
Chris@16 3299 // Element lookup
Chris@16 3300 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 3301 const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
Chris@16 3302 for (;;) {
Chris@16 3303 array_size_type address1 (layout_type::index_M (i, j));
Chris@16 3304 array_size_type address2 (layout_type::index_m (i, j));
Chris@16 3305 vector_const_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
Chris@16 3306 if (filled1_ <= address1 + 1)
Chris@16 3307 return const_iterator1 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
Chris@16 3308
Chris@16 3309 const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
Chris@16 3310 const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
Chris@16 3311
Chris@16 3312 const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
Chris@16 3313 if (rank == 0)
Chris@16 3314 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 3315 if (it != it_end && zero_based (*it) == address2)
Chris@16 3316 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 3317 if (direction > 0) {
Chris@16 3318 if (layout_type::fast_i ()) {
Chris@16 3319 if (it == it_end)
Chris@16 3320 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 3321 i = zero_based (*it);
Chris@16 3322 } else {
Chris@16 3323 if (i >= size1_)
Chris@16 3324 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 3325 ++ i;
Chris@16 3326 }
Chris@16 3327 } else /* if (direction < 0) */ {
Chris@16 3328 if (layout_type::fast_i ()) {
Chris@16 3329 if (it == index2_data_.begin () + zero_based (*itv))
Chris@16 3330 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 3331 i = zero_based (*(it - 1));
Chris@16 3332 } else {
Chris@16 3333 if (i == 0)
Chris@16 3334 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 3335 -- i;
Chris@16 3336 }
Chris@16 3337 }
Chris@16 3338 }
Chris@16 3339 }
Chris@16 3340 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 3341 iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
Chris@16 3342 for (;;) {
Chris@16 3343 array_size_type address1 (layout_type::index_M (i, j));
Chris@16 3344 array_size_type address2 (layout_type::index_m (i, j));
Chris@16 3345 vector_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
Chris@16 3346 if (filled1_ <= address1 + 1)
Chris@16 3347 return iterator1 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
Chris@16 3348
Chris@16 3349 subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
Chris@16 3350 subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
Chris@16 3351
Chris@16 3352 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
Chris@16 3353 if (rank == 0)
Chris@16 3354 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 3355 if (it != it_end && zero_based (*it) == address2)
Chris@16 3356 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 3357 if (direction > 0) {
Chris@16 3358 if (layout_type::fast_i ()) {
Chris@16 3359 if (it == it_end)
Chris@16 3360 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 3361 i = zero_based (*it);
Chris@16 3362 } else {
Chris@16 3363 if (i >= size1_)
Chris@16 3364 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 3365 ++ i;
Chris@16 3366 }
Chris@16 3367 } else /* if (direction < 0) */ {
Chris@16 3368 if (layout_type::fast_i ()) {
Chris@16 3369 if (it == index2_data_.begin () + zero_based (*itv))
Chris@16 3370 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 3371 i = zero_based (*(it - 1));
Chris@16 3372 } else {
Chris@16 3373 if (i == 0)
Chris@16 3374 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 3375 -- i;
Chris@16 3376 }
Chris@16 3377 }
Chris@16 3378 }
Chris@16 3379 }
Chris@16 3380 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 3381 const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
Chris@16 3382 for (;;) {
Chris@16 3383 array_size_type address1 (layout_type::index_M (i, j));
Chris@16 3384 array_size_type address2 (layout_type::index_m (i, j));
Chris@16 3385 vector_const_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
Chris@16 3386 if (filled1_ <= address1 + 1)
Chris@16 3387 return const_iterator2 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
Chris@16 3388
Chris@16 3389 const_subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
Chris@16 3390 const_subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
Chris@16 3391
Chris@16 3392 const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
Chris@16 3393 if (rank == 0)
Chris@16 3394 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 3395 if (it != it_end && zero_based (*it) == address2)
Chris@16 3396 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 3397 if (direction > 0) {
Chris@16 3398 if (layout_type::fast_j ()) {
Chris@16 3399 if (it == it_end)
Chris@16 3400 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 3401 j = zero_based (*it);
Chris@16 3402 } else {
Chris@16 3403 if (j >= size2_)
Chris@16 3404 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 3405 ++ j;
Chris@16 3406 }
Chris@16 3407 } else /* if (direction < 0) */ {
Chris@16 3408 if (layout_type::fast_j ()) {
Chris@16 3409 if (it == index2_data_.begin () + zero_based (*itv))
Chris@16 3410 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 3411 j = zero_based (*(it - 1));
Chris@16 3412 } else {
Chris@16 3413 if (j == 0)
Chris@16 3414 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 3415 -- j;
Chris@16 3416 }
Chris@16 3417 }
Chris@16 3418 }
Chris@16 3419 }
Chris@16 3420 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 3421 iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
Chris@16 3422 for (;;) {
Chris@16 3423 array_size_type address1 (layout_type::index_M (i, j));
Chris@16 3424 array_size_type address2 (layout_type::index_m (i, j));
Chris@16 3425 vector_subiterator_type itv (index1_data_.begin () + (std::min) (filled1_ - 1, address1));
Chris@16 3426 if (filled1_ <= address1 + 1)
Chris@16 3427 return iterator2 (*this, rank, i, j, itv, index2_data_.begin () + filled2_);
Chris@16 3428
Chris@16 3429 subiterator_type it_begin (index2_data_.begin () + zero_based (*itv));
Chris@16 3430 subiterator_type it_end (index2_data_.begin () + zero_based (*(itv + 1)));
Chris@16 3431
Chris@16 3432 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
Chris@16 3433 if (rank == 0)
Chris@16 3434 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 3435 if (it != it_end && zero_based (*it) == address2)
Chris@16 3436 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 3437 if (direction > 0) {
Chris@16 3438 if (layout_type::fast_j ()) {
Chris@16 3439 if (it == it_end)
Chris@16 3440 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 3441 j = zero_based (*it);
Chris@16 3442 } else {
Chris@16 3443 if (j >= size2_)
Chris@16 3444 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 3445 ++ j;
Chris@16 3446 }
Chris@16 3447 } else /* if (direction < 0) */ {
Chris@16 3448 if (layout_type::fast_j ()) {
Chris@16 3449 if (it == index2_data_.begin () + zero_based (*itv))
Chris@16 3450 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 3451 j = zero_based (*(it - 1));
Chris@16 3452 } else {
Chris@16 3453 if (j == 0)
Chris@16 3454 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 3455 -- j;
Chris@16 3456 }
Chris@16 3457 }
Chris@16 3458 }
Chris@16 3459 }
Chris@16 3460
Chris@16 3461
Chris@16 3462 class const_iterator1:
Chris@16 3463 public container_const_reference<compressed_matrix>,
Chris@16 3464 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 3465 const_iterator1, value_type> {
Chris@16 3466 public:
Chris@16 3467 typedef typename compressed_matrix::value_type value_type;
Chris@16 3468 typedef typename compressed_matrix::difference_type difference_type;
Chris@16 3469 typedef typename compressed_matrix::const_reference reference;
Chris@16 3470 typedef const typename compressed_matrix::pointer pointer;
Chris@16 3471
Chris@16 3472 typedef const_iterator2 dual_iterator_type;
Chris@16 3473 typedef const_reverse_iterator2 dual_reverse_iterator_type;
Chris@16 3474
Chris@16 3475 // Construction and destruction
Chris@16 3476 BOOST_UBLAS_INLINE
Chris@16 3477 const_iterator1 ():
Chris@16 3478 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
Chris@16 3479 BOOST_UBLAS_INLINE
Chris@16 3480 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):
Chris@16 3481 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
Chris@16 3482 BOOST_UBLAS_INLINE
Chris@16 3483 const_iterator1 (const iterator1 &it):
Chris@16 3484 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
Chris@16 3485
Chris@16 3486 // Arithmetic
Chris@16 3487 BOOST_UBLAS_INLINE
Chris@16 3488 const_iterator1 &operator ++ () {
Chris@16 3489 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 3490 ++ it_;
Chris@16 3491 else {
Chris@16 3492 i_ = index1 () + 1;
Chris@16 3493 if (rank_ == 1)
Chris@16 3494 *this = (*this) ().find1 (rank_, i_, j_, 1);
Chris@16 3495 }
Chris@16 3496 return *this;
Chris@16 3497 }
Chris@16 3498 BOOST_UBLAS_INLINE
Chris@16 3499 const_iterator1 &operator -- () {
Chris@16 3500 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 3501 -- it_;
Chris@16 3502 else {
Chris@16 3503 --i_;
Chris@16 3504 if (rank_ == 1)
Chris@16 3505 *this = (*this) ().find1 (rank_, i_, j_, -1);
Chris@16 3506 }
Chris@16 3507 return *this;
Chris@16 3508 }
Chris@16 3509
Chris@16 3510 // Dereference
Chris@16 3511 BOOST_UBLAS_INLINE
Chris@16 3512 const_reference operator * () const {
Chris@16 3513 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 3514 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 3515 if (rank_ == 1) {
Chris@16 3516 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
Chris@16 3517 } else {
Chris@16 3518 return (*this) () (i_, j_);
Chris@16 3519 }
Chris@16 3520 }
Chris@16 3521
Chris@16 3522 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 3523 BOOST_UBLAS_INLINE
Chris@16 3524 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 3525 typename self_type::
Chris@16 3526 #endif
Chris@16 3527 const_iterator2 begin () const {
Chris@16 3528 const self_type &m = (*this) ();
Chris@16 3529 return m.find2 (1, index1 (), 0);
Chris@16 3530 }
Chris@16 3531 BOOST_UBLAS_INLINE
Chris@16 3532 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 3533 typename self_type::
Chris@16 3534 #endif
Chris@101 3535 const_iterator2 cbegin () const {
Chris@101 3536 return begin ();
Chris@101 3537 }
Chris@101 3538 BOOST_UBLAS_INLINE
Chris@101 3539 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 3540 typename self_type::
Chris@101 3541 #endif
Chris@16 3542 const_iterator2 end () const {
Chris@16 3543 const self_type &m = (*this) ();
Chris@16 3544 return m.find2 (1, index1 (), m.size2 ());
Chris@16 3545 }
Chris@16 3546 BOOST_UBLAS_INLINE
Chris@16 3547 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 3548 typename self_type::
Chris@16 3549 #endif
Chris@101 3550 const_iterator2 cend () const {
Chris@101 3551 return end ();
Chris@101 3552 }
Chris@101 3553 BOOST_UBLAS_INLINE
Chris@101 3554 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 3555 typename self_type::
Chris@101 3556 #endif
Chris@16 3557 const_reverse_iterator2 rbegin () const {
Chris@16 3558 return const_reverse_iterator2 (end ());
Chris@16 3559 }
Chris@16 3560 BOOST_UBLAS_INLINE
Chris@16 3561 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 3562 typename self_type::
Chris@16 3563 #endif
Chris@101 3564 const_reverse_iterator2 crbegin () const {
Chris@101 3565 return rbegin ();
Chris@101 3566 }
Chris@101 3567 BOOST_UBLAS_INLINE
Chris@101 3568 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 3569 typename self_type::
Chris@101 3570 #endif
Chris@16 3571 const_reverse_iterator2 rend () const {
Chris@16 3572 return const_reverse_iterator2 (begin ());
Chris@16 3573 }
Chris@101 3574 BOOST_UBLAS_INLINE
Chris@101 3575 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 3576 typename self_type::
Chris@101 3577 #endif
Chris@101 3578 const_reverse_iterator2 crend () const {
Chris@101 3579 return rend ();
Chris@101 3580 }
Chris@16 3581 #endif
Chris@16 3582
Chris@16 3583 // Indices
Chris@16 3584 BOOST_UBLAS_INLINE
Chris@16 3585 size_type index1 () const {
Chris@16 3586 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
Chris@16 3587 if (rank_ == 1) {
Chris@16 3588 BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
Chris@16 3589 return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
Chris@16 3590 } else {
Chris@16 3591 return i_;
Chris@16 3592 }
Chris@16 3593 }
Chris@16 3594 BOOST_UBLAS_INLINE
Chris@16 3595 size_type index2 () const {
Chris@16 3596 if (rank_ == 1) {
Chris@16 3597 BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
Chris@16 3598 return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
Chris@16 3599 } else {
Chris@16 3600 return j_;
Chris@16 3601 }
Chris@16 3602 }
Chris@16 3603
Chris@16 3604 // Assignment
Chris@16 3605 BOOST_UBLAS_INLINE
Chris@16 3606 const_iterator1 &operator = (const const_iterator1 &it) {
Chris@16 3607 container_const_reference<self_type>::assign (&it ());
Chris@16 3608 rank_ = it.rank_;
Chris@16 3609 i_ = it.i_;
Chris@16 3610 j_ = it.j_;
Chris@16 3611 itv_ = it.itv_;
Chris@16 3612 it_ = it.it_;
Chris@16 3613 return *this;
Chris@16 3614 }
Chris@16 3615
Chris@16 3616 // Comparison
Chris@16 3617 BOOST_UBLAS_INLINE
Chris@16 3618 bool operator == (const const_iterator1 &it) const {
Chris@16 3619 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 3620 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 3621 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 3622 return it_ == it.it_;
Chris@16 3623 } else {
Chris@16 3624 return i_ == it.i_ && j_ == it.j_;
Chris@16 3625 }
Chris@16 3626 }
Chris@16 3627
Chris@16 3628 private:
Chris@16 3629 int rank_;
Chris@16 3630 size_type i_;
Chris@16 3631 size_type j_;
Chris@16 3632 vector_const_subiterator_type itv_;
Chris@16 3633 const_subiterator_type it_;
Chris@16 3634 };
Chris@16 3635
Chris@16 3636 BOOST_UBLAS_INLINE
Chris@16 3637 const_iterator1 begin1 () const {
Chris@16 3638 return find1 (0, 0, 0);
Chris@16 3639 }
Chris@16 3640 BOOST_UBLAS_INLINE
Chris@101 3641 const_iterator1 cbegin1 () const {
Chris@101 3642 return begin1 ();
Chris@101 3643 }
Chris@101 3644 BOOST_UBLAS_INLINE
Chris@16 3645 const_iterator1 end1 () const {
Chris@16 3646 return find1 (0, size1_, 0);
Chris@16 3647 }
Chris@101 3648 BOOST_UBLAS_INLINE
Chris@101 3649 const_iterator1 cend1 () const {
Chris@101 3650 return end1 ();
Chris@101 3651 }
Chris@16 3652
Chris@16 3653 class iterator1:
Chris@16 3654 public container_reference<compressed_matrix>,
Chris@16 3655 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 3656 iterator1, value_type> {
Chris@16 3657 public:
Chris@16 3658 typedef typename compressed_matrix::value_type value_type;
Chris@16 3659 typedef typename compressed_matrix::difference_type difference_type;
Chris@16 3660 typedef typename compressed_matrix::true_reference reference;
Chris@16 3661 typedef typename compressed_matrix::pointer pointer;
Chris@16 3662
Chris@16 3663 typedef iterator2 dual_iterator_type;
Chris@16 3664 typedef reverse_iterator2 dual_reverse_iterator_type;
Chris@16 3665
Chris@16 3666 // Construction and destruction
Chris@16 3667 BOOST_UBLAS_INLINE
Chris@16 3668 iterator1 ():
Chris@16 3669 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
Chris@16 3670 BOOST_UBLAS_INLINE
Chris@16 3671 iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
Chris@16 3672 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
Chris@16 3673
Chris@16 3674 // Arithmetic
Chris@16 3675 BOOST_UBLAS_INLINE
Chris@16 3676 iterator1 &operator ++ () {
Chris@16 3677 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 3678 ++ it_;
Chris@16 3679 else {
Chris@16 3680 i_ = index1 () + 1;
Chris@16 3681 if (rank_ == 1)
Chris@16 3682 *this = (*this) ().find1 (rank_, i_, j_, 1);
Chris@16 3683 }
Chris@16 3684 return *this;
Chris@16 3685 }
Chris@16 3686 BOOST_UBLAS_INLINE
Chris@16 3687 iterator1 &operator -- () {
Chris@16 3688 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 3689 -- it_;
Chris@16 3690 else {
Chris@16 3691 --i_;
Chris@16 3692 if (rank_ == 1)
Chris@16 3693 *this = (*this) ().find1 (rank_, i_, j_, -1);
Chris@16 3694 }
Chris@16 3695 return *this;
Chris@16 3696 }
Chris@16 3697
Chris@16 3698 // Dereference
Chris@16 3699 BOOST_UBLAS_INLINE
Chris@16 3700 reference operator * () const {
Chris@16 3701 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 3702 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 3703 if (rank_ == 1) {
Chris@16 3704 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
Chris@16 3705 } else {
Chris@16 3706 return (*this) ().at_element (i_, j_);
Chris@16 3707 }
Chris@16 3708 }
Chris@16 3709
Chris@16 3710 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 3711 BOOST_UBLAS_INLINE
Chris@16 3712 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 3713 typename self_type::
Chris@16 3714 #endif
Chris@16 3715 iterator2 begin () const {
Chris@16 3716 self_type &m = (*this) ();
Chris@16 3717 return m.find2 (1, index1 (), 0);
Chris@16 3718 }
Chris@16 3719 BOOST_UBLAS_INLINE
Chris@16 3720 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 3721 typename self_type::
Chris@16 3722 #endif
Chris@16 3723 iterator2 end () const {
Chris@16 3724 self_type &m = (*this) ();
Chris@16 3725 return m.find2 (1, index1 (), m.size2 ());
Chris@16 3726 }
Chris@16 3727 BOOST_UBLAS_INLINE
Chris@16 3728 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 3729 typename self_type::
Chris@16 3730 #endif
Chris@16 3731 reverse_iterator2 rbegin () const {
Chris@16 3732 return reverse_iterator2 (end ());
Chris@16 3733 }
Chris@16 3734 BOOST_UBLAS_INLINE
Chris@16 3735 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 3736 typename self_type::
Chris@16 3737 #endif
Chris@16 3738 reverse_iterator2 rend () const {
Chris@16 3739 return reverse_iterator2 (begin ());
Chris@16 3740 }
Chris@16 3741 #endif
Chris@16 3742
Chris@16 3743 // Indices
Chris@16 3744 BOOST_UBLAS_INLINE
Chris@16 3745 size_type index1 () const {
Chris@16 3746 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
Chris@16 3747 if (rank_ == 1) {
Chris@16 3748 BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
Chris@16 3749 return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
Chris@16 3750 } else {
Chris@16 3751 return i_;
Chris@16 3752 }
Chris@16 3753 }
Chris@16 3754 BOOST_UBLAS_INLINE
Chris@16 3755 size_type index2 () const {
Chris@16 3756 if (rank_ == 1) {
Chris@16 3757 BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
Chris@16 3758 return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
Chris@16 3759 } else {
Chris@16 3760 return j_;
Chris@16 3761 }
Chris@16 3762 }
Chris@16 3763
Chris@16 3764 // Assignment
Chris@16 3765 BOOST_UBLAS_INLINE
Chris@16 3766 iterator1 &operator = (const iterator1 &it) {
Chris@16 3767 container_reference<self_type>::assign (&it ());
Chris@16 3768 rank_ = it.rank_;
Chris@16 3769 i_ = it.i_;
Chris@16 3770 j_ = it.j_;
Chris@16 3771 itv_ = it.itv_;
Chris@16 3772 it_ = it.it_;
Chris@16 3773 return *this;
Chris@16 3774 }
Chris@16 3775
Chris@16 3776 // Comparison
Chris@16 3777 BOOST_UBLAS_INLINE
Chris@16 3778 bool operator == (const iterator1 &it) const {
Chris@16 3779 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 3780 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 3781 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 3782 return it_ == it.it_;
Chris@16 3783 } else {
Chris@16 3784 return i_ == it.i_ && j_ == it.j_;
Chris@16 3785 }
Chris@16 3786 }
Chris@16 3787
Chris@16 3788 private:
Chris@16 3789 int rank_;
Chris@16 3790 size_type i_;
Chris@16 3791 size_type j_;
Chris@16 3792 vector_subiterator_type itv_;
Chris@16 3793 subiterator_type it_;
Chris@16 3794
Chris@16 3795 friend class const_iterator1;
Chris@16 3796 };
Chris@16 3797
Chris@16 3798 BOOST_UBLAS_INLINE
Chris@16 3799 iterator1 begin1 () {
Chris@16 3800 return find1 (0, 0, 0);
Chris@16 3801 }
Chris@16 3802 BOOST_UBLAS_INLINE
Chris@16 3803 iterator1 end1 () {
Chris@16 3804 return find1 (0, size1_, 0);
Chris@16 3805 }
Chris@16 3806
Chris@16 3807 class const_iterator2:
Chris@16 3808 public container_const_reference<compressed_matrix>,
Chris@16 3809 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 3810 const_iterator2, value_type> {
Chris@16 3811 public:
Chris@16 3812 typedef typename compressed_matrix::value_type value_type;
Chris@16 3813 typedef typename compressed_matrix::difference_type difference_type;
Chris@16 3814 typedef typename compressed_matrix::const_reference reference;
Chris@16 3815 typedef const typename compressed_matrix::pointer pointer;
Chris@16 3816
Chris@16 3817 typedef const_iterator1 dual_iterator_type;
Chris@16 3818 typedef const_reverse_iterator1 dual_reverse_iterator_type;
Chris@16 3819
Chris@16 3820 // Construction and destruction
Chris@16 3821 BOOST_UBLAS_INLINE
Chris@16 3822 const_iterator2 ():
Chris@16 3823 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
Chris@16 3824 BOOST_UBLAS_INLINE
Chris@16 3825 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):
Chris@16 3826 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
Chris@16 3827 BOOST_UBLAS_INLINE
Chris@16 3828 const_iterator2 (const iterator2 &it):
Chris@16 3829 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
Chris@16 3830
Chris@16 3831 // Arithmetic
Chris@16 3832 BOOST_UBLAS_INLINE
Chris@16 3833 const_iterator2 &operator ++ () {
Chris@16 3834 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 3835 ++ it_;
Chris@16 3836 else {
Chris@16 3837 j_ = index2 () + 1;
Chris@16 3838 if (rank_ == 1)
Chris@16 3839 *this = (*this) ().find2 (rank_, i_, j_, 1);
Chris@16 3840 }
Chris@16 3841 return *this;
Chris@16 3842 }
Chris@16 3843 BOOST_UBLAS_INLINE
Chris@16 3844 const_iterator2 &operator -- () {
Chris@16 3845 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 3846 -- it_;
Chris@16 3847 else {
Chris@16 3848 --j_;
Chris@16 3849 if (rank_ == 1)
Chris@16 3850 *this = (*this) ().find2 (rank_, i_, j_, -1);
Chris@16 3851 }
Chris@16 3852 return *this;
Chris@16 3853 }
Chris@16 3854
Chris@16 3855 // Dereference
Chris@16 3856 BOOST_UBLAS_INLINE
Chris@16 3857 const_reference operator * () const {
Chris@16 3858 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 3859 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 3860 if (rank_ == 1) {
Chris@16 3861 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
Chris@16 3862 } else {
Chris@16 3863 return (*this) () (i_, j_);
Chris@16 3864 }
Chris@16 3865 }
Chris@16 3866
Chris@16 3867 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 3868 BOOST_UBLAS_INLINE
Chris@16 3869 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 3870 typename self_type::
Chris@16 3871 #endif
Chris@16 3872 const_iterator1 begin () const {
Chris@16 3873 const self_type &m = (*this) ();
Chris@16 3874 return m.find1 (1, 0, index2 ());
Chris@16 3875 }
Chris@16 3876 BOOST_UBLAS_INLINE
Chris@16 3877 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 3878 typename self_type::
Chris@16 3879 #endif
Chris@101 3880 const_iterator1 cbegin () const {
Chris@101 3881 return begin ();
Chris@101 3882 }
Chris@101 3883 BOOST_UBLAS_INLINE
Chris@101 3884 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 3885 typename self_type::
Chris@101 3886 #endif
Chris@16 3887 const_iterator1 end () const {
Chris@16 3888 const self_type &m = (*this) ();
Chris@16 3889 return m.find1 (1, m.size1 (), index2 ());
Chris@16 3890 }
Chris@16 3891 BOOST_UBLAS_INLINE
Chris@16 3892 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 3893 typename self_type::
Chris@16 3894 #endif
Chris@101 3895 const_iterator1 cend () const {
Chris@101 3896 return end ();
Chris@101 3897 }
Chris@101 3898 BOOST_UBLAS_INLINE
Chris@101 3899 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 3900 typename self_type::
Chris@101 3901 #endif
Chris@16 3902 const_reverse_iterator1 rbegin () const {
Chris@16 3903 return const_reverse_iterator1 (end ());
Chris@16 3904 }
Chris@16 3905 BOOST_UBLAS_INLINE
Chris@16 3906 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 3907 typename self_type::
Chris@16 3908 #endif
Chris@101 3909 const_reverse_iterator1 crbegin () const {
Chris@101 3910 return rbegin ();
Chris@101 3911 }
Chris@101 3912 BOOST_UBLAS_INLINE
Chris@101 3913 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 3914 typename self_type::
Chris@101 3915 #endif
Chris@16 3916 const_reverse_iterator1 rend () const {
Chris@16 3917 return const_reverse_iterator1 (begin ());
Chris@16 3918 }
Chris@101 3919 BOOST_UBLAS_INLINE
Chris@101 3920 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 3921 typename self_type::
Chris@101 3922 #endif
Chris@101 3923 const_reverse_iterator1 crend () const {
Chris@101 3924 return rend ();
Chris@101 3925 }
Chris@16 3926 #endif
Chris@16 3927
Chris@16 3928 // Indices
Chris@16 3929 BOOST_UBLAS_INLINE
Chris@16 3930 size_type index1 () const {
Chris@16 3931 if (rank_ == 1) {
Chris@16 3932 BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
Chris@16 3933 return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
Chris@16 3934 } else {
Chris@16 3935 return i_;
Chris@16 3936 }
Chris@16 3937 }
Chris@16 3938 BOOST_UBLAS_INLINE
Chris@16 3939 size_type index2 () const {
Chris@16 3940 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
Chris@16 3941 if (rank_ == 1) {
Chris@16 3942 BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
Chris@16 3943 return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
Chris@16 3944 } else {
Chris@16 3945 return j_;
Chris@16 3946 }
Chris@16 3947 }
Chris@16 3948
Chris@16 3949 // Assignment
Chris@16 3950 BOOST_UBLAS_INLINE
Chris@16 3951 const_iterator2 &operator = (const const_iterator2 &it) {
Chris@16 3952 container_const_reference<self_type>::assign (&it ());
Chris@16 3953 rank_ = it.rank_;
Chris@16 3954 i_ = it.i_;
Chris@16 3955 j_ = it.j_;
Chris@16 3956 itv_ = it.itv_;
Chris@16 3957 it_ = it.it_;
Chris@16 3958 return *this;
Chris@16 3959 }
Chris@16 3960
Chris@16 3961 // Comparison
Chris@16 3962 BOOST_UBLAS_INLINE
Chris@16 3963 bool operator == (const const_iterator2 &it) const {
Chris@16 3964 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 3965 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 3966 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 3967 return it_ == it.it_;
Chris@16 3968 } else {
Chris@16 3969 return i_ == it.i_ && j_ == it.j_;
Chris@16 3970 }
Chris@16 3971 }
Chris@16 3972
Chris@16 3973 private:
Chris@16 3974 int rank_;
Chris@16 3975 size_type i_;
Chris@16 3976 size_type j_;
Chris@16 3977 vector_const_subiterator_type itv_;
Chris@16 3978 const_subiterator_type it_;
Chris@16 3979 };
Chris@16 3980
Chris@16 3981 BOOST_UBLAS_INLINE
Chris@16 3982 const_iterator2 begin2 () const {
Chris@16 3983 return find2 (0, 0, 0);
Chris@16 3984 }
Chris@16 3985 BOOST_UBLAS_INLINE
Chris@101 3986 const_iterator2 cbegin2 () const {
Chris@101 3987 return begin2 ();
Chris@101 3988 }
Chris@101 3989 BOOST_UBLAS_INLINE
Chris@16 3990 const_iterator2 end2 () const {
Chris@16 3991 return find2 (0, 0, size2_);
Chris@16 3992 }
Chris@101 3993 BOOST_UBLAS_INLINE
Chris@101 3994 const_iterator2 cend2 () const {
Chris@101 3995 return end2 ();
Chris@101 3996 }
Chris@16 3997
Chris@16 3998 class iterator2:
Chris@16 3999 public container_reference<compressed_matrix>,
Chris@16 4000 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 4001 iterator2, value_type> {
Chris@16 4002 public:
Chris@16 4003 typedef typename compressed_matrix::value_type value_type;
Chris@16 4004 typedef typename compressed_matrix::difference_type difference_type;
Chris@16 4005 typedef typename compressed_matrix::true_reference reference;
Chris@16 4006 typedef typename compressed_matrix::pointer pointer;
Chris@16 4007
Chris@16 4008 typedef iterator1 dual_iterator_type;
Chris@16 4009 typedef reverse_iterator1 dual_reverse_iterator_type;
Chris@16 4010
Chris@16 4011 // Construction and destruction
Chris@16 4012 BOOST_UBLAS_INLINE
Chris@16 4013 iterator2 ():
Chris@16 4014 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
Chris@16 4015 BOOST_UBLAS_INLINE
Chris@16 4016 iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
Chris@16 4017 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
Chris@16 4018
Chris@16 4019 // Arithmetic
Chris@16 4020 BOOST_UBLAS_INLINE
Chris@16 4021 iterator2 &operator ++ () {
Chris@16 4022 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 4023 ++ it_;
Chris@16 4024 else {
Chris@16 4025 j_ = index2 () + 1;
Chris@16 4026 if (rank_ == 1)
Chris@16 4027 *this = (*this) ().find2 (rank_, i_, j_, 1);
Chris@16 4028 }
Chris@16 4029 return *this;
Chris@16 4030 }
Chris@16 4031 BOOST_UBLAS_INLINE
Chris@16 4032 iterator2 &operator -- () {
Chris@16 4033 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 4034 -- it_;
Chris@16 4035 else {
Chris@16 4036 --j_;
Chris@16 4037 if (rank_ == 1)
Chris@16 4038 *this = (*this) ().find2 (rank_, i_, j_, -1);
Chris@16 4039 }
Chris@16 4040 return *this;
Chris@16 4041 }
Chris@16 4042
Chris@16 4043 // Dereference
Chris@16 4044 BOOST_UBLAS_INLINE
Chris@16 4045 reference operator * () const {
Chris@16 4046 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 4047 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 4048 if (rank_ == 1) {
Chris@16 4049 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
Chris@16 4050 } else {
Chris@16 4051 return (*this) ().at_element (i_, j_);
Chris@16 4052 }
Chris@16 4053 }
Chris@16 4054
Chris@16 4055 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 4056 BOOST_UBLAS_INLINE
Chris@16 4057 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 4058 typename self_type::
Chris@16 4059 #endif
Chris@16 4060 iterator1 begin () const {
Chris@16 4061 self_type &m = (*this) ();
Chris@16 4062 return m.find1 (1, 0, index2 ());
Chris@16 4063 }
Chris@16 4064 BOOST_UBLAS_INLINE
Chris@16 4065 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 4066 typename self_type::
Chris@16 4067 #endif
Chris@16 4068 iterator1 end () const {
Chris@16 4069 self_type &m = (*this) ();
Chris@16 4070 return m.find1 (1, m.size1 (), index2 ());
Chris@16 4071 }
Chris@16 4072 BOOST_UBLAS_INLINE
Chris@16 4073 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 4074 typename self_type::
Chris@16 4075 #endif
Chris@16 4076 reverse_iterator1 rbegin () const {
Chris@16 4077 return reverse_iterator1 (end ());
Chris@16 4078 }
Chris@16 4079 BOOST_UBLAS_INLINE
Chris@16 4080 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 4081 typename self_type::
Chris@16 4082 #endif
Chris@16 4083 reverse_iterator1 rend () const {
Chris@16 4084 return reverse_iterator1 (begin ());
Chris@16 4085 }
Chris@16 4086 #endif
Chris@16 4087
Chris@16 4088 // Indices
Chris@16 4089 BOOST_UBLAS_INLINE
Chris@16 4090 size_type index1 () const {
Chris@16 4091 if (rank_ == 1) {
Chris@16 4092 BOOST_UBLAS_CHECK (layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
Chris@16 4093 return layout_type::index_M (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
Chris@16 4094 } else {
Chris@16 4095 return i_;
Chris@16 4096 }
Chris@16 4097 }
Chris@16 4098 BOOST_UBLAS_INLINE
Chris@16 4099 size_type index2 () const {
Chris@16 4100 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
Chris@16 4101 if (rank_ == 1) {
Chris@16 4102 BOOST_UBLAS_CHECK (layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
Chris@16 4103 return layout_type::index_m (itv_ - (*this) ().index1_data_.begin (), (*this) ().zero_based (*it_));
Chris@16 4104 } else {
Chris@16 4105 return j_;
Chris@16 4106 }
Chris@16 4107 }
Chris@16 4108
Chris@16 4109 // Assignment
Chris@16 4110 BOOST_UBLAS_INLINE
Chris@16 4111 iterator2 &operator = (const iterator2 &it) {
Chris@16 4112 container_reference<self_type>::assign (&it ());
Chris@16 4113 rank_ = it.rank_;
Chris@16 4114 i_ = it.i_;
Chris@16 4115 j_ = it.j_;
Chris@16 4116 itv_ = it.itv_;
Chris@16 4117 it_ = it.it_;
Chris@16 4118 return *this;
Chris@16 4119 }
Chris@16 4120
Chris@16 4121 // Comparison
Chris@16 4122 BOOST_UBLAS_INLINE
Chris@16 4123 bool operator == (const iterator2 &it) const {
Chris@16 4124 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 4125 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 4126 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 4127 return it_ == it.it_;
Chris@16 4128 } else {
Chris@16 4129 return i_ == it.i_ && j_ == it.j_;
Chris@16 4130 }
Chris@16 4131 }
Chris@16 4132
Chris@16 4133 private:
Chris@16 4134 int rank_;
Chris@16 4135 size_type i_;
Chris@16 4136 size_type j_;
Chris@16 4137 vector_subiterator_type itv_;
Chris@16 4138 subiterator_type it_;
Chris@16 4139
Chris@16 4140 friend class const_iterator2;
Chris@16 4141 };
Chris@16 4142
Chris@16 4143 BOOST_UBLAS_INLINE
Chris@16 4144 iterator2 begin2 () {
Chris@16 4145 return find2 (0, 0, 0);
Chris@16 4146 }
Chris@16 4147 BOOST_UBLAS_INLINE
Chris@16 4148 iterator2 end2 () {
Chris@16 4149 return find2 (0, 0, size2_);
Chris@16 4150 }
Chris@16 4151
Chris@16 4152 // Reverse iterators
Chris@16 4153
Chris@16 4154 BOOST_UBLAS_INLINE
Chris@16 4155 const_reverse_iterator1 rbegin1 () const {
Chris@16 4156 return const_reverse_iterator1 (end1 ());
Chris@16 4157 }
Chris@16 4158 BOOST_UBLAS_INLINE
Chris@101 4159 const_reverse_iterator1 crbegin1 () const {
Chris@101 4160 return rbegin1 ();
Chris@101 4161 }
Chris@101 4162 BOOST_UBLAS_INLINE
Chris@16 4163 const_reverse_iterator1 rend1 () const {
Chris@16 4164 return const_reverse_iterator1 (begin1 ());
Chris@16 4165 }
Chris@101 4166 BOOST_UBLAS_INLINE
Chris@101 4167 const_reverse_iterator1 crend1 () const {
Chris@101 4168 return rend1 ();
Chris@101 4169 }
Chris@16 4170
Chris@16 4171 BOOST_UBLAS_INLINE
Chris@16 4172 reverse_iterator1 rbegin1 () {
Chris@16 4173 return reverse_iterator1 (end1 ());
Chris@16 4174 }
Chris@16 4175 BOOST_UBLAS_INLINE
Chris@16 4176 reverse_iterator1 rend1 () {
Chris@16 4177 return reverse_iterator1 (begin1 ());
Chris@16 4178 }
Chris@16 4179
Chris@16 4180 BOOST_UBLAS_INLINE
Chris@16 4181 const_reverse_iterator2 rbegin2 () const {
Chris@16 4182 return const_reverse_iterator2 (end2 ());
Chris@16 4183 }
Chris@16 4184 BOOST_UBLAS_INLINE
Chris@101 4185 const_reverse_iterator2 crbegin2 () const {
Chris@101 4186 return rbegin2 ();
Chris@101 4187 }
Chris@101 4188 BOOST_UBLAS_INLINE
Chris@16 4189 const_reverse_iterator2 rend2 () const {
Chris@16 4190 return const_reverse_iterator2 (begin2 ());
Chris@16 4191 }
Chris@101 4192 BOOST_UBLAS_INLINE
Chris@101 4193 const_reverse_iterator2 crend2 () const {
Chris@101 4194 return rend2 ();
Chris@101 4195 }
Chris@16 4196
Chris@16 4197 BOOST_UBLAS_INLINE
Chris@16 4198 reverse_iterator2 rbegin2 () {
Chris@16 4199 return reverse_iterator2 (end2 ());
Chris@16 4200 }
Chris@16 4201 BOOST_UBLAS_INLINE
Chris@16 4202 reverse_iterator2 rend2 () {
Chris@16 4203 return reverse_iterator2 (begin2 ());
Chris@16 4204 }
Chris@16 4205
Chris@16 4206 // Serialization
Chris@16 4207 template<class Archive>
Chris@16 4208 void serialize(Archive & ar, const unsigned int /* file_version */){
Chris@16 4209 serialization::collection_size_type s1 (size1_);
Chris@16 4210 serialization::collection_size_type s2 (size2_);
Chris@16 4211 ar & serialization::make_nvp("size1",s1);
Chris@16 4212 ar & serialization::make_nvp("size2",s2);
Chris@16 4213 if (Archive::is_loading::value) {
Chris@16 4214 size1_ = s1;
Chris@16 4215 size2_ = s2;
Chris@16 4216 }
Chris@16 4217 ar & serialization::make_nvp("capacity", capacity_);
Chris@16 4218 ar & serialization::make_nvp("filled1", filled1_);
Chris@16 4219 ar & serialization::make_nvp("filled2", filled2_);
Chris@16 4220 ar & serialization::make_nvp("index1_data", index1_data_);
Chris@16 4221 ar & serialization::make_nvp("index2_data", index2_data_);
Chris@16 4222 ar & serialization::make_nvp("value_data", value_data_);
Chris@16 4223 storage_invariants();
Chris@16 4224 }
Chris@16 4225
Chris@16 4226 private:
Chris@16 4227 void storage_invariants () const {
Chris@16 4228 BOOST_UBLAS_CHECK (layout_type::size_M (size1_, size2_) + 1 == index1_data_.size (), internal_logic ());
Chris@16 4229 BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ());
Chris@16 4230 BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
Chris@16 4231 BOOST_UBLAS_CHECK (filled1_ > 0 && filled1_ <= layout_type::size_M (size1_, size2_) + 1, internal_logic ());
Chris@16 4232 BOOST_UBLAS_CHECK (filled2_ <= capacity_, internal_logic ());
Chris@16 4233 BOOST_UBLAS_CHECK (index1_data_ [filled1_ - 1] == k_based (filled2_), internal_logic ());
Chris@16 4234 }
Chris@16 4235
Chris@16 4236 size_type size1_;
Chris@16 4237 size_type size2_;
Chris@16 4238 array_size_type capacity_;
Chris@16 4239 array_size_type filled1_;
Chris@16 4240 array_size_type filled2_;
Chris@16 4241 index_array_type index1_data_;
Chris@16 4242 index_array_type index2_data_;
Chris@16 4243 value_array_type value_data_;
Chris@16 4244 static const value_type zero_;
Chris@16 4245
Chris@16 4246 BOOST_UBLAS_INLINE
Chris@16 4247 static size_type zero_based (size_type k_based_index) {
Chris@16 4248 return k_based_index - IB;
Chris@16 4249 }
Chris@16 4250 BOOST_UBLAS_INLINE
Chris@16 4251 static size_type k_based (size_type zero_based_index) {
Chris@16 4252 return zero_based_index + IB;
Chris@16 4253 }
Chris@16 4254
Chris@16 4255 friend class iterator1;
Chris@16 4256 friend class iterator2;
Chris@16 4257 friend class const_iterator1;
Chris@16 4258 friend class const_iterator2;
Chris@16 4259 };
Chris@16 4260
Chris@16 4261 template<class T, class L, std::size_t IB, class IA, class TA>
Chris@16 4262 const typename compressed_matrix<T, L, IB, IA, TA>::value_type compressed_matrix<T, L, IB, IA, TA>::zero_ = value_type/*zero*/();
Chris@16 4263
Chris@16 4264
Chris@16 4265 // Coordinate array based sparse matrix class
Chris@16 4266 // Thanks to Kresimir Fresl for extending this to cover different index bases.
Chris@16 4267 template<class T, class L, std::size_t IB, class IA, class TA>
Chris@16 4268 class coordinate_matrix:
Chris@16 4269 public matrix_container<coordinate_matrix<T, L, IB, IA, TA> > {
Chris@16 4270
Chris@16 4271 typedef T &true_reference;
Chris@16 4272 typedef T *pointer;
Chris@16 4273 typedef const T *const_pointer;
Chris@16 4274 typedef L layout_type;
Chris@16 4275 typedef coordinate_matrix<T, L, IB, IA, TA> self_type;
Chris@16 4276 public:
Chris@16 4277 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
Chris@16 4278 using matrix_container<self_type>::operator ();
Chris@16 4279 #endif
Chris@16 4280 // ISSUE require type consistency check, is_convertable (IA::size_type, TA::size_type)
Chris@16 4281 typedef typename IA::value_type size_type;
Chris@16 4282 // ISSUE difference_type cannot be deduced for sparse indices, we only know the value_type
Chris@16 4283 typedef std::ptrdiff_t difference_type;
Chris@16 4284 // size_type for the data arrays.
Chris@16 4285 typedef typename IA::size_type array_size_type;
Chris@16 4286 typedef T value_type;
Chris@16 4287 typedef const T &const_reference;
Chris@16 4288 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
Chris@16 4289 typedef T &reference;
Chris@16 4290 #else
Chris@16 4291 typedef sparse_matrix_element<self_type> reference;
Chris@16 4292 #endif
Chris@16 4293 typedef IA index_array_type;
Chris@16 4294 typedef TA value_array_type;
Chris@16 4295 typedef const matrix_reference<const self_type> const_closure_type;
Chris@16 4296 typedef matrix_reference<self_type> closure_type;
Chris@16 4297 typedef coordinate_vector<T, IB, IA, TA> vector_temporary_type;
Chris@16 4298 typedef self_type matrix_temporary_type;
Chris@16 4299 typedef sparse_tag storage_category;
Chris@16 4300 typedef typename L::orientation_category orientation_category;
Chris@16 4301
Chris@16 4302 // Construction and destruction
Chris@16 4303 BOOST_UBLAS_INLINE
Chris@16 4304 coordinate_matrix ():
Chris@16 4305 matrix_container<self_type> (),
Chris@16 4306 size1_ (0), size2_ (0), capacity_ (restrict_capacity (0)),
Chris@16 4307 filled_ (0), sorted_filled_ (filled_), sorted_ (true),
Chris@16 4308 index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) {
Chris@16 4309 storage_invariants ();
Chris@16 4310 }
Chris@16 4311 BOOST_UBLAS_INLINE
Chris@16 4312 coordinate_matrix (size_type size1, size_type size2, array_size_type non_zeros = 0):
Chris@16 4313 matrix_container<self_type> (),
Chris@16 4314 size1_ (size1), size2_ (size2), capacity_ (restrict_capacity (non_zeros)),
Chris@16 4315 filled_ (0), sorted_filled_ (filled_), sorted_ (true),
Chris@16 4316 index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) {
Chris@16 4317 storage_invariants ();
Chris@16 4318 }
Chris@16 4319 BOOST_UBLAS_INLINE
Chris@16 4320 coordinate_matrix (const coordinate_matrix &m):
Chris@16 4321 matrix_container<self_type> (),
Chris@16 4322 size1_ (m.size1_), size2_ (m.size2_), capacity_ (m.capacity_),
Chris@16 4323 filled_ (m.filled_), sorted_filled_ (m.sorted_filled_), sorted_ (m.sorted_),
Chris@16 4324 index1_data_ (m.index1_data_), index2_data_ (m.index2_data_), value_data_ (m.value_data_) {
Chris@16 4325 storage_invariants ();
Chris@16 4326 }
Chris@16 4327 template<class AE>
Chris@16 4328 BOOST_UBLAS_INLINE
Chris@16 4329 coordinate_matrix (const matrix_expression<AE> &ae, array_size_type non_zeros = 0):
Chris@16 4330 matrix_container<self_type> (),
Chris@16 4331 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), capacity_ (restrict_capacity (non_zeros)),
Chris@16 4332 filled_ (0), sorted_filled_ (filled_), sorted_ (true),
Chris@16 4333 index1_data_ (capacity_), index2_data_ (capacity_), value_data_ (capacity_) {
Chris@16 4334 storage_invariants ();
Chris@16 4335 matrix_assign<scalar_assign> (*this, ae);
Chris@16 4336 }
Chris@16 4337
Chris@16 4338 // Accessors
Chris@16 4339 BOOST_UBLAS_INLINE
Chris@16 4340 size_type size1 () const {
Chris@16 4341 return size1_;
Chris@16 4342 }
Chris@16 4343 BOOST_UBLAS_INLINE
Chris@16 4344 size_type size2 () const {
Chris@16 4345 return size2_;
Chris@16 4346 }
Chris@16 4347 BOOST_UBLAS_INLINE
Chris@16 4348 size_type nnz_capacity () const {
Chris@16 4349 return capacity_;
Chris@16 4350 }
Chris@16 4351 BOOST_UBLAS_INLINE
Chris@16 4352 size_type nnz () const {
Chris@16 4353 return filled_;
Chris@16 4354 }
Chris@16 4355
Chris@16 4356 // Storage accessors
Chris@16 4357 BOOST_UBLAS_INLINE
Chris@16 4358 static size_type index_base () {
Chris@16 4359 return IB;
Chris@16 4360 }
Chris@16 4361 BOOST_UBLAS_INLINE
Chris@16 4362 array_size_type filled () const {
Chris@16 4363 return filled_;
Chris@16 4364 }
Chris@16 4365 BOOST_UBLAS_INLINE
Chris@16 4366 const index_array_type &index1_data () const {
Chris@16 4367 return index1_data_;
Chris@16 4368 }
Chris@16 4369 BOOST_UBLAS_INLINE
Chris@16 4370 const index_array_type &index2_data () const {
Chris@16 4371 return index2_data_;
Chris@16 4372 }
Chris@16 4373 BOOST_UBLAS_INLINE
Chris@16 4374 const value_array_type &value_data () const {
Chris@16 4375 return value_data_;
Chris@16 4376 }
Chris@16 4377 BOOST_UBLAS_INLINE
Chris@16 4378 void set_filled (const array_size_type &filled) {
Chris@16 4379 // Make sure that storage_invariants() succeeds
Chris@16 4380 if (sorted_ && filled < filled_)
Chris@16 4381 sorted_filled_ = filled;
Chris@16 4382 else
Chris@16 4383 sorted_ = (sorted_filled_ == filled);
Chris@16 4384 filled_ = filled;
Chris@16 4385 storage_invariants ();
Chris@16 4386 }
Chris@16 4387 BOOST_UBLAS_INLINE
Chris@16 4388 index_array_type &index1_data () {
Chris@16 4389 return index1_data_;
Chris@16 4390 }
Chris@16 4391 BOOST_UBLAS_INLINE
Chris@16 4392 index_array_type &index2_data () {
Chris@16 4393 return index2_data_;
Chris@16 4394 }
Chris@16 4395 BOOST_UBLAS_INLINE
Chris@16 4396 value_array_type &value_data () {
Chris@16 4397 return value_data_;
Chris@16 4398 }
Chris@16 4399
Chris@16 4400 // Resizing
Chris@16 4401 private:
Chris@16 4402 BOOST_UBLAS_INLINE
Chris@16 4403 array_size_type restrict_capacity (array_size_type non_zeros) const {
Chris@16 4404 // minimum non_zeros
Chris@16 4405 non_zeros = (std::max) (non_zeros, array_size_type((std::min) (size1_, size2_)));
Chris@16 4406 // ISSUE no maximum as coordinate may contain inserted duplicates
Chris@16 4407 return non_zeros;
Chris@16 4408 }
Chris@16 4409 public:
Chris@16 4410 BOOST_UBLAS_INLINE
Chris@16 4411 void resize (size_type size1, size_type size2, bool preserve = true) {
Chris@16 4412 // FIXME preserve unimplemented
Chris@16 4413 BOOST_UBLAS_CHECK (!preserve, internal_logic ());
Chris@16 4414 size1_ = size1;
Chris@16 4415 size2_ = size2;
Chris@16 4416 capacity_ = restrict_capacity (capacity_);
Chris@16 4417 index1_data_.resize (capacity_);
Chris@16 4418 index2_data_.resize (capacity_);
Chris@16 4419 value_data_.resize (capacity_);
Chris@16 4420 filled_ = 0;
Chris@16 4421 sorted_filled_ = filled_;
Chris@16 4422 sorted_ = true;
Chris@16 4423 storage_invariants ();
Chris@16 4424 }
Chris@16 4425
Chris@16 4426 // Reserving
Chris@16 4427 BOOST_UBLAS_INLINE
Chris@16 4428 void reserve (array_size_type non_zeros, bool preserve = true) {
Chris@16 4429 sort (); // remove duplicate elements
Chris@16 4430 capacity_ = restrict_capacity (non_zeros);
Chris@16 4431 if (preserve) {
Chris@16 4432 index1_data_.resize (capacity_, size_type ());
Chris@16 4433 index2_data_.resize (capacity_, size_type ());
Chris@16 4434 value_data_.resize (capacity_, value_type ());
Chris@16 4435 filled_ = (std::min) (capacity_, filled_);
Chris@16 4436 }
Chris@16 4437 else {
Chris@16 4438 index1_data_.resize (capacity_);
Chris@16 4439 index2_data_.resize (capacity_);
Chris@16 4440 value_data_.resize (capacity_);
Chris@16 4441 filled_ = 0;
Chris@16 4442 }
Chris@16 4443 sorted_filled_ = filled_;
Chris@16 4444 storage_invariants ();
Chris@16 4445 }
Chris@16 4446
Chris@16 4447 // Element support
Chris@16 4448 BOOST_UBLAS_INLINE
Chris@16 4449 pointer find_element (size_type i, size_type j) {
Chris@16 4450 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
Chris@16 4451 }
Chris@16 4452 BOOST_UBLAS_INLINE
Chris@16 4453 const_pointer find_element (size_type i, size_type j) const {
Chris@16 4454 sort ();
Chris@16 4455 size_type element1 (layout_type::index_M (i, j));
Chris@16 4456 size_type element2 (layout_type::index_m (i, j));
Chris@16 4457 vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
Chris@16 4458 vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
Chris@16 4459 if (itv_begin == itv_end)
Chris@16 4460 return 0;
Chris@16 4461 const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
Chris@16 4462 const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
Chris@16 4463 const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
Chris@16 4464 if (it == it_end || *it != k_based (element2))
Chris@16 4465 return 0;
Chris@16 4466 return &value_data_ [it - index2_data_.begin ()];
Chris@16 4467 }
Chris@16 4468
Chris@16 4469 // Element access
Chris@16 4470 BOOST_UBLAS_INLINE
Chris@16 4471 const_reference operator () (size_type i, size_type j) const {
Chris@16 4472 const_pointer p = find_element (i, j);
Chris@16 4473 if (p)
Chris@16 4474 return *p;
Chris@16 4475 else
Chris@16 4476 return zero_;
Chris@16 4477 }
Chris@16 4478 BOOST_UBLAS_INLINE
Chris@16 4479 reference operator () (size_type i, size_type j) {
Chris@16 4480 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
Chris@16 4481 pointer p = find_element (i, j);
Chris@16 4482 if (p)
Chris@16 4483 return *p;
Chris@16 4484 else
Chris@16 4485 return insert_element (i, j, value_type/*zero*/());
Chris@16 4486 #else
Chris@16 4487 return reference (*this, i, j);
Chris@16 4488 #endif
Chris@16 4489 }
Chris@16 4490
Chris@16 4491 // Element assignment
Chris@16 4492 BOOST_UBLAS_INLINE
Chris@16 4493 void append_element (size_type i, size_type j, const_reference t) {
Chris@16 4494 if (filled_ >= capacity_)
Chris@16 4495 reserve (2 * filled_, true);
Chris@16 4496 BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
Chris@16 4497 size_type element1 = layout_type::index_M (i, j);
Chris@16 4498 size_type element2 = layout_type::index_m (i, j);
Chris@16 4499 index1_data_ [filled_] = k_based (element1);
Chris@16 4500 index2_data_ [filled_] = k_based (element2);
Chris@16 4501 value_data_ [filled_] = t;
Chris@16 4502 ++ filled_;
Chris@16 4503 sorted_ = false;
Chris@16 4504 storage_invariants ();
Chris@16 4505 }
Chris@16 4506 BOOST_UBLAS_INLINE
Chris@16 4507 true_reference insert_element (size_type i, size_type j, const_reference t) {
Chris@16 4508 BOOST_UBLAS_CHECK (!find_element (i, j), bad_index ()); // duplicate element
Chris@16 4509 append_element (i, j, t);
Chris@16 4510 return value_data_ [filled_ - 1];
Chris@16 4511 }
Chris@16 4512 BOOST_UBLAS_INLINE
Chris@16 4513 void erase_element (size_type i, size_type j) {
Chris@16 4514 size_type element1 = layout_type::index_M (i, j);
Chris@16 4515 size_type element2 = layout_type::index_m (i, j);
Chris@16 4516 sort ();
Chris@16 4517 vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
Chris@16 4518 vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (element1), std::less<size_type> ()));
Chris@16 4519 subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
Chris@16 4520 subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
Chris@16 4521 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (element2), std::less<size_type> ()));
Chris@16 4522 if (it != it_end && *it == k_based (element2)) {
Chris@16 4523 typename std::iterator_traits<subiterator_type>::difference_type n = it - index2_data_.begin ();
Chris@16 4524 vector_subiterator_type itv (index1_data_.begin () + n);
Chris@16 4525 std::copy (itv + 1, index1_data_.begin () + filled_, itv);
Chris@16 4526 std::copy (it + 1, index2_data_.begin () + filled_, it);
Chris@16 4527 typename value_array_type::iterator itt (value_data_.begin () + n);
Chris@16 4528 std::copy (itt + 1, value_data_.begin () + filled_, itt);
Chris@16 4529 -- filled_;
Chris@16 4530 sorted_filled_ = filled_;
Chris@16 4531 }
Chris@16 4532 storage_invariants ();
Chris@16 4533 }
Chris@16 4534
Chris@16 4535 // Zeroing
Chris@16 4536 BOOST_UBLAS_INLINE
Chris@16 4537 void clear () {
Chris@16 4538 filled_ = 0;
Chris@16 4539 sorted_filled_ = filled_;
Chris@16 4540 sorted_ = true;
Chris@16 4541 storage_invariants ();
Chris@16 4542 }
Chris@16 4543
Chris@16 4544 // Assignment
Chris@16 4545 BOOST_UBLAS_INLINE
Chris@16 4546 coordinate_matrix &operator = (const coordinate_matrix &m) {
Chris@16 4547 if (this != &m) {
Chris@16 4548 size1_ = m.size1_;
Chris@16 4549 size2_ = m.size2_;
Chris@16 4550 capacity_ = m.capacity_;
Chris@16 4551 filled_ = m.filled_;
Chris@16 4552 sorted_filled_ = m.sorted_filled_;
Chris@16 4553 sorted_ = m.sorted_;
Chris@16 4554 index1_data_ = m.index1_data_;
Chris@16 4555 index2_data_ = m.index2_data_;
Chris@16 4556 value_data_ = m.value_data_;
Chris@16 4557 BOOST_UBLAS_CHECK (capacity_ == index1_data_.size (), internal_logic ());
Chris@16 4558 BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ());
Chris@16 4559 BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
Chris@16 4560 }
Chris@16 4561 storage_invariants ();
Chris@16 4562 return *this;
Chris@16 4563 }
Chris@16 4564 template<class C> // Container assignment without temporary
Chris@16 4565 BOOST_UBLAS_INLINE
Chris@16 4566 coordinate_matrix &operator = (const matrix_container<C> &m) {
Chris@16 4567 resize (m ().size1 (), m ().size2 (), false);
Chris@16 4568 assign (m);
Chris@16 4569 return *this;
Chris@16 4570 }
Chris@16 4571 BOOST_UBLAS_INLINE
Chris@16 4572 coordinate_matrix &assign_temporary (coordinate_matrix &m) {
Chris@16 4573 swap (m);
Chris@16 4574 return *this;
Chris@16 4575 }
Chris@16 4576 template<class AE>
Chris@16 4577 BOOST_UBLAS_INLINE
Chris@16 4578 coordinate_matrix &operator = (const matrix_expression<AE> &ae) {
Chris@16 4579 self_type temporary (ae, capacity_);
Chris@16 4580 return assign_temporary (temporary);
Chris@16 4581 }
Chris@16 4582 template<class AE>
Chris@16 4583 BOOST_UBLAS_INLINE
Chris@16 4584 coordinate_matrix &assign (const matrix_expression<AE> &ae) {
Chris@16 4585 matrix_assign<scalar_assign> (*this, ae);
Chris@16 4586 return *this;
Chris@16 4587 }
Chris@16 4588 template<class AE>
Chris@16 4589 BOOST_UBLAS_INLINE
Chris@16 4590 coordinate_matrix& operator += (const matrix_expression<AE> &ae) {
Chris@16 4591 self_type temporary (*this + ae, capacity_);
Chris@16 4592 return assign_temporary (temporary);
Chris@16 4593 }
Chris@16 4594 template<class C> // Container assignment without temporary
Chris@16 4595 BOOST_UBLAS_INLINE
Chris@16 4596 coordinate_matrix &operator += (const matrix_container<C> &m) {
Chris@16 4597 plus_assign (m);
Chris@16 4598 return *this;
Chris@16 4599 }
Chris@16 4600 template<class AE>
Chris@16 4601 BOOST_UBLAS_INLINE
Chris@16 4602 coordinate_matrix &plus_assign (const matrix_expression<AE> &ae) {
Chris@16 4603 matrix_assign<scalar_plus_assign> (*this, ae);
Chris@16 4604 return *this;
Chris@16 4605 }
Chris@16 4606 template<class AE>
Chris@16 4607 BOOST_UBLAS_INLINE
Chris@16 4608 coordinate_matrix& operator -= (const matrix_expression<AE> &ae) {
Chris@16 4609 self_type temporary (*this - ae, capacity_);
Chris@16 4610 return assign_temporary (temporary);
Chris@16 4611 }
Chris@16 4612 template<class C> // Container assignment without temporary
Chris@16 4613 BOOST_UBLAS_INLINE
Chris@16 4614 coordinate_matrix &operator -= (const matrix_container<C> &m) {
Chris@16 4615 minus_assign (m);
Chris@16 4616 return *this;
Chris@16 4617 }
Chris@16 4618 template<class AE>
Chris@16 4619 BOOST_UBLAS_INLINE
Chris@16 4620 coordinate_matrix &minus_assign (const matrix_expression<AE> &ae) {
Chris@16 4621 matrix_assign<scalar_minus_assign> (*this, ae);
Chris@16 4622 return *this;
Chris@16 4623 }
Chris@16 4624 template<class AT>
Chris@16 4625 BOOST_UBLAS_INLINE
Chris@16 4626 coordinate_matrix& operator *= (const AT &at) {
Chris@16 4627 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
Chris@16 4628 return *this;
Chris@16 4629 }
Chris@16 4630 template<class AT>
Chris@16 4631 BOOST_UBLAS_INLINE
Chris@16 4632 coordinate_matrix& operator /= (const AT &at) {
Chris@16 4633 matrix_assign_scalar<scalar_divides_assign> (*this, at);
Chris@16 4634 return *this;
Chris@16 4635 }
Chris@16 4636
Chris@16 4637 // Swapping
Chris@16 4638 BOOST_UBLAS_INLINE
Chris@16 4639 void swap (coordinate_matrix &m) {
Chris@16 4640 if (this != &m) {
Chris@16 4641 std::swap (size1_, m.size1_);
Chris@16 4642 std::swap (size2_, m.size2_);
Chris@16 4643 std::swap (capacity_, m.capacity_);
Chris@16 4644 std::swap (filled_, m.filled_);
Chris@16 4645 std::swap (sorted_filled_, m.sorted_filled_);
Chris@16 4646 std::swap (sorted_, m.sorted_);
Chris@16 4647 index1_data_.swap (m.index1_data_);
Chris@16 4648 index2_data_.swap (m.index2_data_);
Chris@16 4649 value_data_.swap (m.value_data_);
Chris@16 4650 }
Chris@16 4651 storage_invariants ();
Chris@16 4652 }
Chris@16 4653 BOOST_UBLAS_INLINE
Chris@16 4654 friend void swap (coordinate_matrix &m1, coordinate_matrix &m2) {
Chris@16 4655 m1.swap (m2);
Chris@16 4656 }
Chris@16 4657
Chris@16 4658 // replacement if STL lower bound algorithm for use of inplace_merge
Chris@16 4659 array_size_type lower_bound (array_size_type beg, array_size_type end, array_size_type target) const {
Chris@16 4660 while (end > beg) {
Chris@16 4661 array_size_type mid = (beg + end) / 2;
Chris@16 4662 if (((index1_data_[mid] < index1_data_[target]) ||
Chris@16 4663 ((index1_data_[mid] == index1_data_[target]) &&
Chris@16 4664 (index2_data_[mid] < index2_data_[target])))) {
Chris@16 4665 beg = mid + 1;
Chris@16 4666 } else {
Chris@16 4667 end = mid;
Chris@16 4668 }
Chris@16 4669 }
Chris@16 4670 return beg;
Chris@16 4671 }
Chris@16 4672
Chris@16 4673 // specialized replacement of STL inplace_merge to avoid compilation
Chris@16 4674 // problems with respect to the array_triple iterator
Chris@16 4675 void inplace_merge (array_size_type beg, array_size_type mid, array_size_type end) const {
Chris@16 4676 array_size_type len_lef = mid - beg;
Chris@16 4677 array_size_type len_rig = end - mid;
Chris@16 4678
Chris@16 4679 if (len_lef == 1 && len_rig == 1) {
Chris@16 4680 if ((index1_data_[mid] < index1_data_[beg]) ||
Chris@16 4681 ((index1_data_[mid] == index1_data_[beg]) && (index2_data_[mid] < index2_data_[beg])))
Chris@16 4682 {
Chris@16 4683 std::swap(index1_data_[beg], index1_data_[mid]);
Chris@16 4684 std::swap(index2_data_[beg], index2_data_[mid]);
Chris@16 4685 std::swap(value_data_[beg], value_data_[mid]);
Chris@16 4686 }
Chris@16 4687 } else if (len_lef > 0 && len_rig > 0) {
Chris@16 4688 array_size_type lef_mid, rig_mid;
Chris@16 4689 if (len_lef >= len_rig) {
Chris@16 4690 lef_mid = (beg + mid) / 2;
Chris@16 4691 rig_mid = lower_bound(mid, end, lef_mid);
Chris@16 4692 } else {
Chris@16 4693 rig_mid = (mid + end) / 2;
Chris@16 4694 lef_mid = lower_bound(beg, mid, rig_mid);
Chris@16 4695 }
Chris@16 4696 std::rotate(&index1_data_[0] + lef_mid, &index1_data_[0] + mid, &index1_data_[0] + rig_mid);
Chris@16 4697 std::rotate(&index2_data_[0] + lef_mid, &index2_data_[0] + mid, &index2_data_[0] + rig_mid);
Chris@16 4698 std::rotate(&value_data_[0] + lef_mid, &value_data_[0] + mid, &value_data_[0] + rig_mid);
Chris@16 4699
Chris@16 4700 array_size_type new_mid = lef_mid + rig_mid - mid;
Chris@16 4701 inplace_merge(beg, lef_mid, new_mid);
Chris@16 4702 inplace_merge(new_mid, rig_mid, end);
Chris@16 4703 }
Chris@16 4704 }
Chris@16 4705
Chris@16 4706 // Sorting and summation of duplicates
Chris@16 4707 BOOST_UBLAS_INLINE
Chris@16 4708 void sort () const {
Chris@16 4709 if (! sorted_ && filled_ > 0) {
Chris@16 4710 typedef index_triple_array<index_array_type, index_array_type, value_array_type> array_triple;
Chris@16 4711 array_triple ita (filled_, index1_data_, index2_data_, value_data_);
Chris@16 4712 #ifndef BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT
Chris@16 4713 const typename array_triple::iterator iunsorted = ita.begin () + sorted_filled_;
Chris@16 4714 // sort new elements and merge
Chris@16 4715 std::sort (iunsorted, ita.end ());
Chris@16 4716 inplace_merge(0, sorted_filled_, filled_);
Chris@16 4717 #else
Chris@16 4718 const typename array_triple::iterator iunsorted = ita.begin ();
Chris@16 4719 std::sort (iunsorted, ita.end ());
Chris@16 4720 #endif
Chris@16 4721 // sum duplicates with += and remove
Chris@16 4722 array_size_type filled = 0;
Chris@16 4723 for (array_size_type i = 1; i < filled_; ++ i) {
Chris@16 4724 if (index1_data_ [filled] != index1_data_ [i] ||
Chris@16 4725 index2_data_ [filled] != index2_data_ [i]) {
Chris@16 4726 ++ filled;
Chris@16 4727 if (filled != i) {
Chris@16 4728 index1_data_ [filled] = index1_data_ [i];
Chris@16 4729 index2_data_ [filled] = index2_data_ [i];
Chris@16 4730 value_data_ [filled] = value_data_ [i];
Chris@16 4731 }
Chris@16 4732 } else {
Chris@16 4733 value_data_ [filled] += value_data_ [i];
Chris@16 4734 }
Chris@16 4735 }
Chris@16 4736 filled_ = filled + 1;
Chris@16 4737 sorted_filled_ = filled_;
Chris@16 4738 sorted_ = true;
Chris@16 4739 storage_invariants ();
Chris@16 4740 }
Chris@16 4741 }
Chris@16 4742
Chris@16 4743 // Back element insertion and erasure
Chris@16 4744 BOOST_UBLAS_INLINE
Chris@16 4745 void push_back (size_type i, size_type j, const_reference t) {
Chris@16 4746 size_type element1 = layout_type::index_M (i, j);
Chris@16 4747 size_type element2 = layout_type::index_m (i, j);
Chris@16 4748 // must maintain sort order
Chris@16 4749 BOOST_UBLAS_CHECK (sorted_ &&
Chris@16 4750 (filled_ == 0 ||
Chris@16 4751 index1_data_ [filled_ - 1] < k_based (element1) ||
Chris@16 4752 (index1_data_ [filled_ - 1] == k_based (element1) && index2_data_ [filled_ - 1] < k_based (element2)))
Chris@16 4753 , external_logic ());
Chris@16 4754 if (filled_ >= capacity_)
Chris@16 4755 reserve (2 * filled_, true);
Chris@16 4756 BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
Chris@16 4757 index1_data_ [filled_] = k_based (element1);
Chris@16 4758 index2_data_ [filled_] = k_based (element2);
Chris@16 4759 value_data_ [filled_] = t;
Chris@16 4760 ++ filled_;
Chris@16 4761 sorted_filled_ = filled_;
Chris@16 4762 storage_invariants ();
Chris@16 4763 }
Chris@16 4764 BOOST_UBLAS_INLINE
Chris@16 4765 void pop_back () {
Chris@16 4766 // ISSUE invariants could be simpilfied if sorted required as precondition
Chris@16 4767 BOOST_UBLAS_CHECK (filled_ > 0, external_logic ());
Chris@16 4768 -- filled_;
Chris@16 4769 sorted_filled_ = (std::min) (sorted_filled_, filled_);
Chris@16 4770 sorted_ = sorted_filled_ = filled_;
Chris@16 4771 storage_invariants ();
Chris@16 4772 }
Chris@16 4773
Chris@16 4774 // Iterator types
Chris@16 4775 private:
Chris@16 4776 // Use index array iterator
Chris@16 4777 typedef typename IA::const_iterator vector_const_subiterator_type;
Chris@16 4778 typedef typename IA::iterator vector_subiterator_type;
Chris@16 4779 typedef typename IA::const_iterator const_subiterator_type;
Chris@16 4780 typedef typename IA::iterator subiterator_type;
Chris@16 4781
Chris@16 4782 BOOST_UBLAS_INLINE
Chris@16 4783 true_reference at_element (size_type i, size_type j) {
Chris@16 4784 pointer p = find_element (i, j);
Chris@16 4785 BOOST_UBLAS_CHECK (p, bad_index ());
Chris@16 4786 return *p;
Chris@16 4787 }
Chris@16 4788
Chris@16 4789 public:
Chris@16 4790 class const_iterator1;
Chris@16 4791 class iterator1;
Chris@16 4792 class const_iterator2;
Chris@16 4793 class iterator2;
Chris@16 4794 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
Chris@16 4795 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
Chris@16 4796 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
Chris@16 4797 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
Chris@16 4798
Chris@16 4799 // Element lookup
Chris@16 4800 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 4801 const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
Chris@16 4802 sort ();
Chris@16 4803 for (;;) {
Chris@16 4804 size_type address1 (layout_type::index_M (i, j));
Chris@16 4805 size_type address2 (layout_type::index_m (i, j));
Chris@16 4806 vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
Chris@16 4807 vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
Chris@16 4808
Chris@16 4809 const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
Chris@16 4810 const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
Chris@16 4811
Chris@16 4812 const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
Chris@16 4813 vector_const_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
Chris@16 4814 if (rank == 0)
Chris@16 4815 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 4816 if (it != it_end && zero_based (*it) == address2)
Chris@16 4817 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 4818 if (direction > 0) {
Chris@16 4819 if (layout_type::fast_i ()) {
Chris@16 4820 if (it == it_end)
Chris@16 4821 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 4822 i = zero_based (*it);
Chris@16 4823 } else {
Chris@16 4824 if (i >= size1_)
Chris@16 4825 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 4826 ++ i;
Chris@16 4827 }
Chris@16 4828 } else /* if (direction < 0) */ {
Chris@16 4829 if (layout_type::fast_i ()) {
Chris@16 4830 if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
Chris@16 4831 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 4832 i = zero_based (*(it - 1));
Chris@16 4833 } else {
Chris@16 4834 if (i == 0)
Chris@16 4835 return const_iterator1 (*this, rank, i, j, itv, it);
Chris@16 4836 -- i;
Chris@16 4837 }
Chris@16 4838 }
Chris@16 4839 }
Chris@16 4840 }
Chris@16 4841 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 4842 iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
Chris@16 4843 sort ();
Chris@16 4844 for (;;) {
Chris@16 4845 size_type address1 (layout_type::index_M (i, j));
Chris@16 4846 size_type address2 (layout_type::index_m (i, j));
Chris@16 4847 vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
Chris@16 4848 vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
Chris@16 4849
Chris@16 4850 subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
Chris@16 4851 subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
Chris@16 4852
Chris@16 4853 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
Chris@16 4854 vector_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
Chris@16 4855 if (rank == 0)
Chris@16 4856 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 4857 if (it != it_end && zero_based (*it) == address2)
Chris@16 4858 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 4859 if (direction > 0) {
Chris@16 4860 if (layout_type::fast_i ()) {
Chris@16 4861 if (it == it_end)
Chris@16 4862 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 4863 i = zero_based (*it);
Chris@16 4864 } else {
Chris@16 4865 if (i >= size1_)
Chris@16 4866 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 4867 ++ i;
Chris@16 4868 }
Chris@16 4869 } else /* if (direction < 0) */ {
Chris@16 4870 if (layout_type::fast_i ()) {
Chris@16 4871 if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
Chris@16 4872 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 4873 i = zero_based (*(it - 1));
Chris@16 4874 } else {
Chris@16 4875 if (i == 0)
Chris@16 4876 return iterator1 (*this, rank, i, j, itv, it);
Chris@16 4877 -- i;
Chris@16 4878 }
Chris@16 4879 }
Chris@16 4880 }
Chris@16 4881 }
Chris@16 4882 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 4883 const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
Chris@16 4884 sort ();
Chris@16 4885 for (;;) {
Chris@16 4886 size_type address1 (layout_type::index_M (i, j));
Chris@16 4887 size_type address2 (layout_type::index_m (i, j));
Chris@16 4888 vector_const_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
Chris@16 4889 vector_const_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
Chris@16 4890
Chris@16 4891 const_subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
Chris@16 4892 const_subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
Chris@16 4893
Chris@16 4894 const_subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
Chris@16 4895 vector_const_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
Chris@16 4896 if (rank == 0)
Chris@16 4897 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 4898 if (it != it_end && zero_based (*it) == address2)
Chris@16 4899 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 4900 if (direction > 0) {
Chris@16 4901 if (layout_type::fast_j ()) {
Chris@16 4902 if (it == it_end)
Chris@16 4903 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 4904 j = zero_based (*it);
Chris@16 4905 } else {
Chris@16 4906 if (j >= size2_)
Chris@16 4907 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 4908 ++ j;
Chris@16 4909 }
Chris@16 4910 } else /* if (direction < 0) */ {
Chris@16 4911 if (layout_type::fast_j ()) {
Chris@16 4912 if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
Chris@16 4913 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 4914 j = zero_based (*(it - 1));
Chris@16 4915 } else {
Chris@16 4916 if (j == 0)
Chris@16 4917 return const_iterator2 (*this, rank, i, j, itv, it);
Chris@16 4918 -- j;
Chris@16 4919 }
Chris@16 4920 }
Chris@16 4921 }
Chris@16 4922 }
Chris@16 4923 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 4924 iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
Chris@16 4925 sort ();
Chris@16 4926 for (;;) {
Chris@16 4927 size_type address1 (layout_type::index_M (i, j));
Chris@16 4928 size_type address2 (layout_type::index_m (i, j));
Chris@16 4929 vector_subiterator_type itv_begin (detail::lower_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
Chris@16 4930 vector_subiterator_type itv_end (detail::upper_bound (index1_data_.begin (), index1_data_.begin () + filled_, k_based (address1), std::less<size_type> ()));
Chris@16 4931
Chris@16 4932 subiterator_type it_begin (index2_data_.begin () + (itv_begin - index1_data_.begin ()));
Chris@16 4933 subiterator_type it_end (index2_data_.begin () + (itv_end - index1_data_.begin ()));
Chris@16 4934
Chris@16 4935 subiterator_type it (detail::lower_bound (it_begin, it_end, k_based (address2), std::less<size_type> ()));
Chris@16 4936 vector_subiterator_type itv (index1_data_.begin () + (it - index2_data_.begin ()));
Chris@16 4937 if (rank == 0)
Chris@16 4938 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 4939 if (it != it_end && zero_based (*it) == address2)
Chris@16 4940 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 4941 if (direction > 0) {
Chris@16 4942 if (layout_type::fast_j ()) {
Chris@16 4943 if (it == it_end)
Chris@16 4944 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 4945 j = zero_based (*it);
Chris@16 4946 } else {
Chris@16 4947 if (j >= size2_)
Chris@16 4948 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 4949 ++ j;
Chris@16 4950 }
Chris@16 4951 } else /* if (direction < 0) */ {
Chris@16 4952 if (layout_type::fast_j ()) {
Chris@16 4953 if (it == index2_data_.begin () + array_size_type (zero_based (*itv)))
Chris@16 4954 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 4955 j = zero_based (*(it - 1));
Chris@16 4956 } else {
Chris@16 4957 if (j == 0)
Chris@16 4958 return iterator2 (*this, rank, i, j, itv, it);
Chris@16 4959 -- j;
Chris@16 4960 }
Chris@16 4961 }
Chris@16 4962 }
Chris@16 4963 }
Chris@16 4964
Chris@16 4965
Chris@16 4966 class const_iterator1:
Chris@16 4967 public container_const_reference<coordinate_matrix>,
Chris@16 4968 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 4969 const_iterator1, value_type> {
Chris@16 4970 public:
Chris@16 4971 typedef typename coordinate_matrix::value_type value_type;
Chris@16 4972 typedef typename coordinate_matrix::difference_type difference_type;
Chris@16 4973 typedef typename coordinate_matrix::const_reference reference;
Chris@16 4974 typedef const typename coordinate_matrix::pointer pointer;
Chris@16 4975
Chris@16 4976 typedef const_iterator2 dual_iterator_type;
Chris@16 4977 typedef const_reverse_iterator2 dual_reverse_iterator_type;
Chris@16 4978
Chris@16 4979 // Construction and destruction
Chris@16 4980 BOOST_UBLAS_INLINE
Chris@16 4981 const_iterator1 ():
Chris@16 4982 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
Chris@16 4983 BOOST_UBLAS_INLINE
Chris@16 4984 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):
Chris@16 4985 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
Chris@16 4986 BOOST_UBLAS_INLINE
Chris@16 4987 const_iterator1 (const iterator1 &it):
Chris@16 4988 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
Chris@16 4989
Chris@16 4990 // Arithmetic
Chris@16 4991 BOOST_UBLAS_INLINE
Chris@16 4992 const_iterator1 &operator ++ () {
Chris@16 4993 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 4994 ++ it_;
Chris@16 4995 else {
Chris@16 4996 i_ = index1 () + 1;
Chris@16 4997 if (rank_ == 1)
Chris@16 4998 *this = (*this) ().find1 (rank_, i_, j_, 1);
Chris@16 4999 }
Chris@16 5000 return *this;
Chris@16 5001 }
Chris@16 5002 BOOST_UBLAS_INLINE
Chris@16 5003 const_iterator1 &operator -- () {
Chris@16 5004 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 5005 -- it_;
Chris@16 5006 else {
Chris@16 5007 i_ = index1 () - 1;
Chris@16 5008 if (rank_ == 1)
Chris@16 5009 *this = (*this) ().find1 (rank_, i_, j_, -1);
Chris@16 5010 }
Chris@16 5011 return *this;
Chris@16 5012 }
Chris@16 5013
Chris@16 5014 // Dereference
Chris@16 5015 BOOST_UBLAS_INLINE
Chris@16 5016 const_reference operator * () const {
Chris@16 5017 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 5018 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 5019 if (rank_ == 1) {
Chris@16 5020 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
Chris@16 5021 } else {
Chris@16 5022 return (*this) () (i_, j_);
Chris@16 5023 }
Chris@16 5024 }
Chris@16 5025
Chris@16 5026 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 5027 BOOST_UBLAS_INLINE
Chris@16 5028 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5029 typename self_type::
Chris@16 5030 #endif
Chris@16 5031 const_iterator2 begin () const {
Chris@16 5032 const self_type &m = (*this) ();
Chris@16 5033 return m.find2 (1, index1 (), 0);
Chris@16 5034 }
Chris@16 5035 BOOST_UBLAS_INLINE
Chris@16 5036 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5037 typename self_type::
Chris@16 5038 #endif
Chris@101 5039 const_iterator2 cbegin () const {
Chris@101 5040 return begin ();
Chris@101 5041 }
Chris@101 5042 BOOST_UBLAS_INLINE
Chris@101 5043 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 5044 typename self_type::
Chris@101 5045 #endif
Chris@16 5046 const_iterator2 end () const {
Chris@16 5047 const self_type &m = (*this) ();
Chris@16 5048 return m.find2 (1, index1 (), m.size2 ());
Chris@16 5049 }
Chris@16 5050 BOOST_UBLAS_INLINE
Chris@16 5051 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5052 typename self_type::
Chris@16 5053 #endif
Chris@101 5054 const_iterator2 cend () const {
Chris@101 5055 return end ();
Chris@101 5056 }
Chris@101 5057 BOOST_UBLAS_INLINE
Chris@101 5058 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 5059 typename self_type::
Chris@101 5060 #endif
Chris@16 5061 const_reverse_iterator2 rbegin () const {
Chris@16 5062 return const_reverse_iterator2 (end ());
Chris@16 5063 }
Chris@16 5064 BOOST_UBLAS_INLINE
Chris@16 5065 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5066 typename self_type::
Chris@16 5067 #endif
Chris@101 5068 const_reverse_iterator2 crbegin () const {
Chris@101 5069 return rbegin ();
Chris@101 5070 }
Chris@101 5071 BOOST_UBLAS_INLINE
Chris@101 5072 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 5073 typename self_type::
Chris@101 5074 #endif
Chris@16 5075 const_reverse_iterator2 rend () const {
Chris@16 5076 return const_reverse_iterator2 (begin ());
Chris@16 5077 }
Chris@101 5078 BOOST_UBLAS_INLINE
Chris@101 5079 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 5080 typename self_type::
Chris@101 5081 #endif
Chris@101 5082 const_reverse_iterator2 crend () const {
Chris@101 5083 return rend ();
Chris@101 5084 }
Chris@16 5085 #endif
Chris@16 5086
Chris@16 5087 // Indices
Chris@16 5088 BOOST_UBLAS_INLINE
Chris@16 5089 size_type index1 () const {
Chris@16 5090 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
Chris@16 5091 if (rank_ == 1) {
Chris@16 5092 BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
Chris@16 5093 return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
Chris@16 5094 } else {
Chris@16 5095 return i_;
Chris@16 5096 }
Chris@16 5097 }
Chris@16 5098 BOOST_UBLAS_INLINE
Chris@16 5099 size_type index2 () const {
Chris@16 5100 if (rank_ == 1) {
Chris@16 5101 BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
Chris@16 5102 return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
Chris@16 5103 } else {
Chris@16 5104 return j_;
Chris@16 5105 }
Chris@16 5106 }
Chris@16 5107
Chris@16 5108 // Assignment
Chris@16 5109 BOOST_UBLAS_INLINE
Chris@16 5110 const_iterator1 &operator = (const const_iterator1 &it) {
Chris@16 5111 container_const_reference<self_type>::assign (&it ());
Chris@16 5112 rank_ = it.rank_;
Chris@16 5113 i_ = it.i_;
Chris@16 5114 j_ = it.j_;
Chris@16 5115 itv_ = it.itv_;
Chris@16 5116 it_ = it.it_;
Chris@16 5117 return *this;
Chris@16 5118 }
Chris@16 5119
Chris@16 5120 // Comparison
Chris@16 5121 BOOST_UBLAS_INLINE
Chris@16 5122 bool operator == (const const_iterator1 &it) const {
Chris@16 5123 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 5124 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 5125 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 5126 return it_ == it.it_;
Chris@16 5127 } else {
Chris@16 5128 return i_ == it.i_ && j_ == it.j_;
Chris@16 5129 }
Chris@16 5130 }
Chris@16 5131
Chris@16 5132 private:
Chris@16 5133 int rank_;
Chris@16 5134 size_type i_;
Chris@16 5135 size_type j_;
Chris@16 5136 vector_const_subiterator_type itv_;
Chris@16 5137 const_subiterator_type it_;
Chris@16 5138 };
Chris@16 5139
Chris@16 5140 BOOST_UBLAS_INLINE
Chris@16 5141 const_iterator1 begin1 () const {
Chris@16 5142 return find1 (0, 0, 0);
Chris@16 5143 }
Chris@16 5144 BOOST_UBLAS_INLINE
Chris@101 5145 const_iterator1 cbegin1 () const {
Chris@101 5146 return begin1 ();
Chris@101 5147 }
Chris@101 5148 BOOST_UBLAS_INLINE
Chris@16 5149 const_iterator1 end1 () const {
Chris@16 5150 return find1 (0, size1_, 0);
Chris@16 5151 }
Chris@101 5152 BOOST_UBLAS_INLINE
Chris@101 5153 const_iterator1 cend1 () const {
Chris@101 5154 return end1 ();
Chris@101 5155 }
Chris@16 5156
Chris@16 5157 class iterator1:
Chris@16 5158 public container_reference<coordinate_matrix>,
Chris@16 5159 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 5160 iterator1, value_type> {
Chris@16 5161 public:
Chris@16 5162 typedef typename coordinate_matrix::value_type value_type;
Chris@16 5163 typedef typename coordinate_matrix::difference_type difference_type;
Chris@16 5164 typedef typename coordinate_matrix::true_reference reference;
Chris@16 5165 typedef typename coordinate_matrix::pointer pointer;
Chris@16 5166
Chris@16 5167 typedef iterator2 dual_iterator_type;
Chris@16 5168 typedef reverse_iterator2 dual_reverse_iterator_type;
Chris@16 5169
Chris@16 5170 // Construction and destruction
Chris@16 5171 BOOST_UBLAS_INLINE
Chris@16 5172 iterator1 ():
Chris@16 5173 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
Chris@16 5174 BOOST_UBLAS_INLINE
Chris@16 5175 iterator1 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
Chris@16 5176 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
Chris@16 5177
Chris@16 5178 // Arithmetic
Chris@16 5179 BOOST_UBLAS_INLINE
Chris@16 5180 iterator1 &operator ++ () {
Chris@16 5181 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 5182 ++ it_;
Chris@16 5183 else {
Chris@16 5184 i_ = index1 () + 1;
Chris@16 5185 if (rank_ == 1)
Chris@16 5186 *this = (*this) ().find1 (rank_, i_, j_, 1);
Chris@16 5187 }
Chris@16 5188 return *this;
Chris@16 5189 }
Chris@16 5190 BOOST_UBLAS_INLINE
Chris@16 5191 iterator1 &operator -- () {
Chris@16 5192 if (rank_ == 1 && layout_type::fast_i ())
Chris@16 5193 -- it_;
Chris@16 5194 else {
Chris@16 5195 i_ = index1 () - 1;
Chris@16 5196 if (rank_ == 1)
Chris@16 5197 *this = (*this) ().find1 (rank_, i_, j_, -1);
Chris@16 5198 }
Chris@16 5199 return *this;
Chris@16 5200 }
Chris@16 5201
Chris@16 5202 // Dereference
Chris@16 5203 BOOST_UBLAS_INLINE
Chris@16 5204 reference operator * () const {
Chris@16 5205 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 5206 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 5207 if (rank_ == 1) {
Chris@16 5208 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
Chris@16 5209 } else {
Chris@16 5210 return (*this) ().at_element (i_, j_);
Chris@16 5211 }
Chris@16 5212 }
Chris@16 5213
Chris@16 5214 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 5215 BOOST_UBLAS_INLINE
Chris@16 5216 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5217 typename self_type::
Chris@16 5218 #endif
Chris@16 5219 iterator2 begin () const {
Chris@16 5220 self_type &m = (*this) ();
Chris@16 5221 return m.find2 (1, index1 (), 0);
Chris@16 5222 }
Chris@16 5223 BOOST_UBLAS_INLINE
Chris@16 5224 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5225 typename self_type::
Chris@16 5226 #endif
Chris@16 5227 iterator2 end () const {
Chris@16 5228 self_type &m = (*this) ();
Chris@16 5229 return m.find2 (1, index1 (), m.size2 ());
Chris@16 5230 }
Chris@16 5231 BOOST_UBLAS_INLINE
Chris@16 5232 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5233 typename self_type::
Chris@16 5234 #endif
Chris@16 5235 reverse_iterator2 rbegin () const {
Chris@16 5236 return reverse_iterator2 (end ());
Chris@16 5237 }
Chris@16 5238 BOOST_UBLAS_INLINE
Chris@16 5239 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5240 typename self_type::
Chris@16 5241 #endif
Chris@16 5242 reverse_iterator2 rend () const {
Chris@16 5243 return reverse_iterator2 (begin ());
Chris@16 5244 }
Chris@16 5245 #endif
Chris@16 5246
Chris@16 5247 // Indices
Chris@16 5248 BOOST_UBLAS_INLINE
Chris@16 5249 size_type index1 () const {
Chris@16 5250 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
Chris@16 5251 if (rank_ == 1) {
Chris@16 5252 BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
Chris@16 5253 return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
Chris@16 5254 } else {
Chris@16 5255 return i_;
Chris@16 5256 }
Chris@16 5257 }
Chris@16 5258 BOOST_UBLAS_INLINE
Chris@16 5259 size_type index2 () const {
Chris@16 5260 if (rank_ == 1) {
Chris@16 5261 BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
Chris@16 5262 return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
Chris@16 5263 } else {
Chris@16 5264 return j_;
Chris@16 5265 }
Chris@16 5266 }
Chris@16 5267
Chris@16 5268 // Assignment
Chris@16 5269 BOOST_UBLAS_INLINE
Chris@16 5270 iterator1 &operator = (const iterator1 &it) {
Chris@16 5271 container_reference<self_type>::assign (&it ());
Chris@16 5272 rank_ = it.rank_;
Chris@16 5273 i_ = it.i_;
Chris@16 5274 j_ = it.j_;
Chris@16 5275 itv_ = it.itv_;
Chris@16 5276 it_ = it.it_;
Chris@16 5277 return *this;
Chris@16 5278 }
Chris@16 5279
Chris@16 5280 // Comparison
Chris@16 5281 BOOST_UBLAS_INLINE
Chris@16 5282 bool operator == (const iterator1 &it) const {
Chris@16 5283 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 5284 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 5285 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 5286 return it_ == it.it_;
Chris@16 5287 } else {
Chris@16 5288 return i_ == it.i_ && j_ == it.j_;
Chris@16 5289 }
Chris@16 5290 }
Chris@16 5291
Chris@16 5292 private:
Chris@16 5293 int rank_;
Chris@16 5294 size_type i_;
Chris@16 5295 size_type j_;
Chris@16 5296 vector_subiterator_type itv_;
Chris@16 5297 subiterator_type it_;
Chris@16 5298
Chris@16 5299 friend class const_iterator1;
Chris@16 5300 };
Chris@16 5301
Chris@16 5302 BOOST_UBLAS_INLINE
Chris@16 5303 iterator1 begin1 () {
Chris@16 5304 return find1 (0, 0, 0);
Chris@16 5305 }
Chris@16 5306 BOOST_UBLAS_INLINE
Chris@16 5307 iterator1 end1 () {
Chris@16 5308 return find1 (0, size1_, 0);
Chris@16 5309 }
Chris@16 5310
Chris@16 5311 class const_iterator2:
Chris@16 5312 public container_const_reference<coordinate_matrix>,
Chris@16 5313 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 5314 const_iterator2, value_type> {
Chris@16 5315 public:
Chris@16 5316 typedef typename coordinate_matrix::value_type value_type;
Chris@16 5317 typedef typename coordinate_matrix::difference_type difference_type;
Chris@16 5318 typedef typename coordinate_matrix::const_reference reference;
Chris@16 5319 typedef const typename coordinate_matrix::pointer pointer;
Chris@16 5320
Chris@16 5321 typedef const_iterator1 dual_iterator_type;
Chris@16 5322 typedef const_reverse_iterator1 dual_reverse_iterator_type;
Chris@16 5323
Chris@16 5324 // Construction and destruction
Chris@16 5325 BOOST_UBLAS_INLINE
Chris@16 5326 const_iterator2 ():
Chris@16 5327 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
Chris@16 5328 BOOST_UBLAS_INLINE
Chris@16 5329 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):
Chris@16 5330 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
Chris@16 5331 BOOST_UBLAS_INLINE
Chris@16 5332 const_iterator2 (const iterator2 &it):
Chris@16 5333 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
Chris@16 5334
Chris@16 5335 // Arithmetic
Chris@16 5336 BOOST_UBLAS_INLINE
Chris@16 5337 const_iterator2 &operator ++ () {
Chris@16 5338 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 5339 ++ it_;
Chris@16 5340 else {
Chris@16 5341 j_ = index2 () + 1;
Chris@16 5342 if (rank_ == 1)
Chris@16 5343 *this = (*this) ().find2 (rank_, i_, j_, 1);
Chris@16 5344 }
Chris@16 5345 return *this;
Chris@16 5346 }
Chris@16 5347 BOOST_UBLAS_INLINE
Chris@16 5348 const_iterator2 &operator -- () {
Chris@16 5349 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 5350 -- it_;
Chris@16 5351 else {
Chris@16 5352 j_ = index2 () - 1;
Chris@16 5353 if (rank_ == 1)
Chris@16 5354 *this = (*this) ().find2 (rank_, i_, j_, -1);
Chris@16 5355 }
Chris@16 5356 return *this;
Chris@16 5357 }
Chris@16 5358
Chris@16 5359 // Dereference
Chris@16 5360 BOOST_UBLAS_INLINE
Chris@16 5361 const_reference operator * () const {
Chris@16 5362 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 5363 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 5364 if (rank_ == 1) {
Chris@16 5365 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
Chris@16 5366 } else {
Chris@16 5367 return (*this) () (i_, j_);
Chris@16 5368 }
Chris@16 5369 }
Chris@16 5370
Chris@16 5371 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 5372 BOOST_UBLAS_INLINE
Chris@16 5373 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5374 typename self_type::
Chris@16 5375 #endif
Chris@16 5376 const_iterator1 begin () const {
Chris@16 5377 const self_type &m = (*this) ();
Chris@16 5378 return m.find1 (1, 0, index2 ());
Chris@16 5379 }
Chris@16 5380 BOOST_UBLAS_INLINE
Chris@16 5381 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5382 typename self_type::
Chris@16 5383 #endif
Chris@101 5384 const_iterator1 cbegin () const {
Chris@101 5385 return begin ();
Chris@101 5386 }
Chris@101 5387 BOOST_UBLAS_INLINE
Chris@101 5388 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 5389 typename self_type::
Chris@101 5390 #endif
Chris@16 5391 const_iterator1 end () const {
Chris@16 5392 const self_type &m = (*this) ();
Chris@16 5393 return m.find1 (1, m.size1 (), index2 ());
Chris@16 5394 }
Chris@16 5395 BOOST_UBLAS_INLINE
Chris@16 5396 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5397 typename self_type::
Chris@16 5398 #endif
Chris@101 5399 const_iterator1 cend () const {
Chris@101 5400 return end ();
Chris@101 5401 }
Chris@101 5402 BOOST_UBLAS_INLINE
Chris@101 5403 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 5404 typename self_type::
Chris@101 5405 #endif
Chris@16 5406 const_reverse_iterator1 rbegin () const {
Chris@16 5407 return const_reverse_iterator1 (end ());
Chris@16 5408 }
Chris@16 5409 BOOST_UBLAS_INLINE
Chris@16 5410 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5411 typename self_type::
Chris@16 5412 #endif
Chris@101 5413 const_reverse_iterator1 crbegin () const {
Chris@101 5414 return rbegin ();
Chris@101 5415 }
Chris@101 5416 BOOST_UBLAS_INLINE
Chris@101 5417 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 5418 typename self_type::
Chris@101 5419 #endif
Chris@16 5420 const_reverse_iterator1 rend () const {
Chris@16 5421 return const_reverse_iterator1 (begin ());
Chris@16 5422 }
Chris@101 5423 BOOST_UBLAS_INLINE
Chris@101 5424 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@101 5425 typename self_type::
Chris@101 5426 #endif
Chris@101 5427 const_reverse_iterator1 crend () const {
Chris@101 5428 return rend ();
Chris@101 5429 }
Chris@16 5430 #endif
Chris@16 5431
Chris@16 5432 // Indices
Chris@16 5433 BOOST_UBLAS_INLINE
Chris@16 5434 size_type index1 () const {
Chris@16 5435 if (rank_ == 1) {
Chris@16 5436 BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
Chris@16 5437 return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
Chris@16 5438 } else {
Chris@16 5439 return i_;
Chris@16 5440 }
Chris@16 5441 }
Chris@16 5442 BOOST_UBLAS_INLINE
Chris@16 5443 size_type index2 () const {
Chris@16 5444 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
Chris@16 5445 if (rank_ == 1) {
Chris@16 5446 BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
Chris@16 5447 return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
Chris@16 5448 } else {
Chris@16 5449 return j_;
Chris@16 5450 }
Chris@16 5451 }
Chris@16 5452
Chris@16 5453 // Assignment
Chris@16 5454 BOOST_UBLAS_INLINE
Chris@16 5455 const_iterator2 &operator = (const const_iterator2 &it) {
Chris@16 5456 container_const_reference<self_type>::assign (&it ());
Chris@16 5457 rank_ = it.rank_;
Chris@16 5458 i_ = it.i_;
Chris@16 5459 j_ = it.j_;
Chris@16 5460 itv_ = it.itv_;
Chris@16 5461 it_ = it.it_;
Chris@16 5462 return *this;
Chris@16 5463 }
Chris@16 5464
Chris@16 5465 // Comparison
Chris@16 5466 BOOST_UBLAS_INLINE
Chris@16 5467 bool operator == (const const_iterator2 &it) const {
Chris@16 5468 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 5469 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 5470 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 5471 return it_ == it.it_;
Chris@16 5472 } else {
Chris@16 5473 return i_ == it.i_ && j_ == it.j_;
Chris@16 5474 }
Chris@16 5475 }
Chris@16 5476
Chris@16 5477 private:
Chris@16 5478 int rank_;
Chris@16 5479 size_type i_;
Chris@16 5480 size_type j_;
Chris@16 5481 vector_const_subiterator_type itv_;
Chris@16 5482 const_subiterator_type it_;
Chris@16 5483 };
Chris@16 5484
Chris@16 5485 BOOST_UBLAS_INLINE
Chris@16 5486 const_iterator2 begin2 () const {
Chris@16 5487 return find2 (0, 0, 0);
Chris@16 5488 }
Chris@16 5489 BOOST_UBLAS_INLINE
Chris@101 5490 const_iterator2 cbegin2 () const {
Chris@101 5491 return begin2 ();
Chris@101 5492 }
Chris@101 5493 BOOST_UBLAS_INLINE
Chris@16 5494 const_iterator2 end2 () const {
Chris@16 5495 return find2 (0, 0, size2_);
Chris@16 5496 }
Chris@101 5497 BOOST_UBLAS_INLINE
Chris@101 5498 const_iterator2 cend2 () const {
Chris@101 5499 return end2 ();
Chris@101 5500 }
Chris@16 5501
Chris@16 5502 class iterator2:
Chris@16 5503 public container_reference<coordinate_matrix>,
Chris@16 5504 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 5505 iterator2, value_type> {
Chris@16 5506 public:
Chris@16 5507 typedef typename coordinate_matrix::value_type value_type;
Chris@16 5508 typedef typename coordinate_matrix::difference_type difference_type;
Chris@16 5509 typedef typename coordinate_matrix::true_reference reference;
Chris@16 5510 typedef typename coordinate_matrix::pointer pointer;
Chris@16 5511
Chris@16 5512 typedef iterator1 dual_iterator_type;
Chris@16 5513 typedef reverse_iterator1 dual_reverse_iterator_type;
Chris@16 5514
Chris@16 5515 // Construction and destruction
Chris@16 5516 BOOST_UBLAS_INLINE
Chris@16 5517 iterator2 ():
Chris@16 5518 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
Chris@16 5519 BOOST_UBLAS_INLINE
Chris@16 5520 iterator2 (self_type &m, int rank, size_type i, size_type j, const vector_subiterator_type &itv, const subiterator_type &it):
Chris@16 5521 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
Chris@16 5522
Chris@16 5523 // Arithmetic
Chris@16 5524 BOOST_UBLAS_INLINE
Chris@16 5525 iterator2 &operator ++ () {
Chris@16 5526 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 5527 ++ it_;
Chris@16 5528 else {
Chris@16 5529 j_ = index2 () + 1;
Chris@16 5530 if (rank_ == 1)
Chris@16 5531 *this = (*this) ().find2 (rank_, i_, j_, 1);
Chris@16 5532 }
Chris@16 5533 return *this;
Chris@16 5534 }
Chris@16 5535 BOOST_UBLAS_INLINE
Chris@16 5536 iterator2 &operator -- () {
Chris@16 5537 if (rank_ == 1 && layout_type::fast_j ())
Chris@16 5538 -- it_;
Chris@16 5539 else {
Chris@16 5540 j_ = index2 ();
Chris@16 5541 if (rank_ == 1)
Chris@16 5542 *this = (*this) ().find2 (rank_, i_, j_, -1);
Chris@16 5543 }
Chris@16 5544 return *this;
Chris@16 5545 }
Chris@16 5546
Chris@16 5547 // Dereference
Chris@16 5548 BOOST_UBLAS_INLINE
Chris@16 5549 reference operator * () const {
Chris@16 5550 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
Chris@16 5551 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
Chris@16 5552 if (rank_ == 1) {
Chris@16 5553 return (*this) ().value_data_ [it_ - (*this) ().index2_data_.begin ()];
Chris@16 5554 } else {
Chris@16 5555 return (*this) ().at_element (i_, j_);
Chris@16 5556 }
Chris@16 5557 }
Chris@16 5558
Chris@16 5559 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
Chris@16 5560 BOOST_UBLAS_INLINE
Chris@16 5561 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5562 typename self_type::
Chris@16 5563 #endif
Chris@16 5564 iterator1 begin () const {
Chris@16 5565 self_type &m = (*this) ();
Chris@16 5566 return m.find1 (1, 0, index2 ());
Chris@16 5567 }
Chris@16 5568 BOOST_UBLAS_INLINE
Chris@16 5569 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5570 typename self_type::
Chris@16 5571 #endif
Chris@16 5572 iterator1 end () const {
Chris@16 5573 self_type &m = (*this) ();
Chris@16 5574 return m.find1 (1, m.size1 (), index2 ());
Chris@16 5575 }
Chris@16 5576 BOOST_UBLAS_INLINE
Chris@16 5577 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5578 typename self_type::
Chris@16 5579 #endif
Chris@16 5580 reverse_iterator1 rbegin () const {
Chris@16 5581 return reverse_iterator1 (end ());
Chris@16 5582 }
Chris@16 5583 BOOST_UBLAS_INLINE
Chris@16 5584 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
Chris@16 5585 typename self_type::
Chris@16 5586 #endif
Chris@16 5587 reverse_iterator1 rend () const {
Chris@16 5588 return reverse_iterator1 (begin ());
Chris@16 5589 }
Chris@16 5590 #endif
Chris@16 5591
Chris@16 5592 // Indices
Chris@16 5593 BOOST_UBLAS_INLINE
Chris@16 5594 size_type index1 () const {
Chris@16 5595 if (rank_ == 1) {
Chris@16 5596 BOOST_UBLAS_CHECK (layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size1 (), bad_index ());
Chris@16 5597 return layout_type::index_M ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
Chris@16 5598 } else {
Chris@16 5599 return i_;
Chris@16 5600 }
Chris@16 5601 }
Chris@16 5602 BOOST_UBLAS_INLINE
Chris@16 5603 size_type index2 () const {
Chris@16 5604 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
Chris@16 5605 if (rank_ == 1) {
Chris@16 5606 BOOST_UBLAS_CHECK (layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_)) < (*this) ().size2 (), bad_index ());
Chris@16 5607 return layout_type::index_m ((*this) ().zero_based (*itv_), (*this) ().zero_based (*it_));
Chris@16 5608 } else {
Chris@16 5609 return j_;
Chris@16 5610 }
Chris@16 5611 }
Chris@16 5612
Chris@16 5613 // Assignment
Chris@16 5614 BOOST_UBLAS_INLINE
Chris@16 5615 iterator2 &operator = (const iterator2 &it) {
Chris@16 5616 container_reference<self_type>::assign (&it ());
Chris@16 5617 rank_ = it.rank_;
Chris@16 5618 i_ = it.i_;
Chris@16 5619 j_ = it.j_;
Chris@16 5620 itv_ = it.itv_;
Chris@16 5621 it_ = it.it_;
Chris@16 5622 return *this;
Chris@16 5623 }
Chris@16 5624
Chris@16 5625 // Comparison
Chris@16 5626 BOOST_UBLAS_INLINE
Chris@16 5627 bool operator == (const iterator2 &it) const {
Chris@16 5628 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 5629 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
Chris@16 5630 if (rank_ == 1 || it.rank_ == 1) {
Chris@16 5631 return it_ == it.it_;
Chris@16 5632 } else {
Chris@16 5633 return i_ == it.i_ && j_ == it.j_;
Chris@16 5634 }
Chris@16 5635 }
Chris@16 5636
Chris@16 5637 private:
Chris@16 5638 int rank_;
Chris@16 5639 size_type i_;
Chris@16 5640 size_type j_;
Chris@16 5641 vector_subiterator_type itv_;
Chris@16 5642 subiterator_type it_;
Chris@16 5643
Chris@16 5644 friend class const_iterator2;
Chris@16 5645 };
Chris@16 5646
Chris@16 5647 BOOST_UBLAS_INLINE
Chris@16 5648 iterator2 begin2 () {
Chris@16 5649 return find2 (0, 0, 0);
Chris@16 5650 }
Chris@16 5651 BOOST_UBLAS_INLINE
Chris@16 5652 iterator2 end2 () {
Chris@16 5653 return find2 (0, 0, size2_);
Chris@16 5654 }
Chris@16 5655
Chris@16 5656 // Reverse iterators
Chris@16 5657
Chris@16 5658 BOOST_UBLAS_INLINE
Chris@16 5659 const_reverse_iterator1 rbegin1 () const {
Chris@16 5660 return const_reverse_iterator1 (end1 ());
Chris@16 5661 }
Chris@16 5662 BOOST_UBLAS_INLINE
Chris@101 5663 const_reverse_iterator1 crbegin1 () const {
Chris@101 5664 return rbegin1 ();
Chris@101 5665 }
Chris@101 5666 BOOST_UBLAS_INLINE
Chris@16 5667 const_reverse_iterator1 rend1 () const {
Chris@16 5668 return const_reverse_iterator1 (begin1 ());
Chris@16 5669 }
Chris@101 5670 BOOST_UBLAS_INLINE
Chris@101 5671 const_reverse_iterator1 crend1 () const {
Chris@101 5672 return rend1 ();
Chris@101 5673 }
Chris@16 5674
Chris@16 5675 BOOST_UBLAS_INLINE
Chris@16 5676 reverse_iterator1 rbegin1 () {
Chris@16 5677 return reverse_iterator1 (end1 ());
Chris@16 5678 }
Chris@16 5679 BOOST_UBLAS_INLINE
Chris@16 5680 reverse_iterator1 rend1 () {
Chris@16 5681 return reverse_iterator1 (begin1 ());
Chris@16 5682 }
Chris@16 5683
Chris@16 5684 BOOST_UBLAS_INLINE
Chris@16 5685 const_reverse_iterator2 rbegin2 () const {
Chris@16 5686 return const_reverse_iterator2 (end2 ());
Chris@16 5687 }
Chris@16 5688 BOOST_UBLAS_INLINE
Chris@101 5689 const_reverse_iterator2 crbegin2 () const {
Chris@101 5690 return rbegin2 ();
Chris@101 5691 }
Chris@101 5692 BOOST_UBLAS_INLINE
Chris@16 5693 const_reverse_iterator2 rend2 () const {
Chris@16 5694 return const_reverse_iterator2 (begin2 ());
Chris@16 5695 }
Chris@101 5696 BOOST_UBLAS_INLINE
Chris@101 5697 const_reverse_iterator2 crend2 () const {
Chris@101 5698 return rend2 ();
Chris@101 5699 }
Chris@16 5700
Chris@16 5701 BOOST_UBLAS_INLINE
Chris@16 5702 reverse_iterator2 rbegin2 () {
Chris@16 5703 return reverse_iterator2 (end2 ());
Chris@16 5704 }
Chris@16 5705 BOOST_UBLAS_INLINE
Chris@16 5706 reverse_iterator2 rend2 () {
Chris@16 5707 return reverse_iterator2 (begin2 ());
Chris@16 5708 }
Chris@16 5709
Chris@16 5710 // Serialization
Chris@16 5711 template<class Archive>
Chris@16 5712 void serialize(Archive & ar, const unsigned int /* file_version */){
Chris@16 5713 serialization::collection_size_type s1 (size1_);
Chris@16 5714 serialization::collection_size_type s2 (size2_);
Chris@16 5715 ar & serialization::make_nvp("size1",s1);
Chris@16 5716 ar & serialization::make_nvp("size2",s2);
Chris@16 5717 if (Archive::is_loading::value) {
Chris@16 5718 size1_ = s1;
Chris@16 5719 size2_ = s2;
Chris@16 5720 }
Chris@16 5721 ar & serialization::make_nvp("capacity", capacity_);
Chris@16 5722 ar & serialization::make_nvp("filled", filled_);
Chris@16 5723 ar & serialization::make_nvp("sorted_filled", sorted_filled_);
Chris@16 5724 ar & serialization::make_nvp("sorted", sorted_);
Chris@16 5725 ar & serialization::make_nvp("index1_data", index1_data_);
Chris@16 5726 ar & serialization::make_nvp("index2_data", index2_data_);
Chris@16 5727 ar & serialization::make_nvp("value_data", value_data_);
Chris@16 5728 storage_invariants();
Chris@16 5729 }
Chris@16 5730
Chris@16 5731 private:
Chris@16 5732 void storage_invariants () const
Chris@16 5733 {
Chris@16 5734 BOOST_UBLAS_CHECK (capacity_ == index1_data_.size (), internal_logic ());
Chris@16 5735 BOOST_UBLAS_CHECK (capacity_ == index2_data_.size (), internal_logic ());
Chris@16 5736 BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
Chris@16 5737 BOOST_UBLAS_CHECK (filled_ <= capacity_, internal_logic ());
Chris@16 5738 BOOST_UBLAS_CHECK (sorted_filled_ <= filled_, internal_logic ());
Chris@16 5739 BOOST_UBLAS_CHECK (sorted_ == (sorted_filled_ == filled_), internal_logic ());
Chris@16 5740 }
Chris@16 5741
Chris@16 5742 size_type size1_;
Chris@16 5743 size_type size2_;
Chris@16 5744 array_size_type capacity_;
Chris@16 5745 mutable array_size_type filled_;
Chris@16 5746 mutable array_size_type sorted_filled_;
Chris@16 5747 mutable bool sorted_;
Chris@16 5748 mutable index_array_type index1_data_;
Chris@16 5749 mutable index_array_type index2_data_;
Chris@16 5750 mutable value_array_type value_data_;
Chris@16 5751 static const value_type zero_;
Chris@16 5752
Chris@16 5753 BOOST_UBLAS_INLINE
Chris@16 5754 static size_type zero_based (size_type k_based_index) {
Chris@16 5755 return k_based_index - IB;
Chris@16 5756 }
Chris@16 5757 BOOST_UBLAS_INLINE
Chris@16 5758 static size_type k_based (size_type zero_based_index) {
Chris@16 5759 return zero_based_index + IB;
Chris@16 5760 }
Chris@16 5761
Chris@16 5762 friend class iterator1;
Chris@16 5763 friend class iterator2;
Chris@16 5764 friend class const_iterator1;
Chris@16 5765 friend class const_iterator2;
Chris@16 5766 };
Chris@16 5767
Chris@16 5768 template<class T, class L, std::size_t IB, class IA, class TA>
Chris@16 5769 const typename coordinate_matrix<T, L, IB, IA, TA>::value_type coordinate_matrix<T, L, IB, IA, TA>::zero_ = value_type/*zero*/();
Chris@16 5770
Chris@16 5771 }}}
Chris@16 5772
Chris@16 5773 #endif