annotate DEPENDENCIES/generic/include/boost/numeric/ublas/vector_sparse.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //
Chris@16 2 // Copyright (c) 2000-2002
Chris@16 3 // Joerg Walter, Mathias Koch
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_VECTOR_SPARSE_
Chris@16 14 #define _BOOST_UBLAS_VECTOR_SPARSE_
Chris@16 15
Chris@16 16 #include <boost/numeric/ublas/storage_sparse.hpp>
Chris@16 17 #include <boost/numeric/ublas/vector_expression.hpp>
Chris@16 18 #include <boost/numeric/ublas/detail/vector_assign.hpp>
Chris@16 19 #if BOOST_UBLAS_TYPE_CHECK
Chris@16 20 #include <boost/numeric/ublas/vector.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_VECTOR_SPARSE
Chris@16 28
Chris@16 29 template<class V>
Chris@16 30 class sparse_vector_element:
Chris@16 31 public container_reference<V> {
Chris@16 32 public:
Chris@16 33 typedef V vector_type;
Chris@16 34 typedef typename V::size_type size_type;
Chris@16 35 typedef typename V::value_type value_type;
Chris@16 36 typedef const value_type &const_reference;
Chris@16 37 typedef value_type *pointer;
Chris@16 38
Chris@16 39 private:
Chris@16 40 // Proxied element operations
Chris@16 41 void get_d () const {
Chris@16 42 pointer p = (*this) ().find_element (i_);
Chris@16 43 if (p)
Chris@16 44 d_ = *p;
Chris@16 45 else
Chris@16 46 d_ = value_type/*zero*/();
Chris@16 47 }
Chris@16 48
Chris@16 49 void set (const value_type &s) const {
Chris@16 50 pointer p = (*this) ().find_element (i_);
Chris@16 51 if (!p)
Chris@16 52 (*this) ().insert_element (i_, s);
Chris@16 53 else
Chris@16 54 *p = s;
Chris@16 55 }
Chris@16 56
Chris@16 57 public:
Chris@16 58 // Construction and destruction
Chris@16 59 sparse_vector_element (vector_type &v, size_type i):
Chris@16 60 container_reference<vector_type> (v), i_ (i) {
Chris@16 61 }
Chris@16 62 BOOST_UBLAS_INLINE
Chris@16 63 sparse_vector_element (const sparse_vector_element &p):
Chris@16 64 container_reference<vector_type> (p), i_ (p.i_) {}
Chris@16 65 BOOST_UBLAS_INLINE
Chris@16 66 ~sparse_vector_element () {
Chris@16 67 }
Chris@16 68
Chris@16 69 // Assignment
Chris@16 70 BOOST_UBLAS_INLINE
Chris@16 71 sparse_vector_element &operator = (const sparse_vector_element &p) {
Chris@16 72 // Overide the implict copy assignment
Chris@16 73 p.get_d ();
Chris@16 74 set (p.d_);
Chris@16 75 return *this;
Chris@16 76 }
Chris@16 77 template<class D>
Chris@16 78 BOOST_UBLAS_INLINE
Chris@16 79 sparse_vector_element &operator = (const D &d) {
Chris@16 80 set (d);
Chris@16 81 return *this;
Chris@16 82 }
Chris@16 83 template<class D>
Chris@16 84 BOOST_UBLAS_INLINE
Chris@16 85 sparse_vector_element &operator += (const D &d) {
Chris@16 86 get_d ();
Chris@16 87 d_ += d;
Chris@16 88 set (d_);
Chris@16 89 return *this;
Chris@16 90 }
Chris@16 91 template<class D>
Chris@16 92 BOOST_UBLAS_INLINE
Chris@16 93 sparse_vector_element &operator -= (const D &d) {
Chris@16 94 get_d ();
Chris@16 95 d_ -= d;
Chris@16 96 set (d_);
Chris@16 97 return *this;
Chris@16 98 }
Chris@16 99 template<class D>
Chris@16 100 BOOST_UBLAS_INLINE
Chris@16 101 sparse_vector_element &operator *= (const D &d) {
Chris@16 102 get_d ();
Chris@16 103 d_ *= d;
Chris@16 104 set (d_);
Chris@16 105 return *this;
Chris@16 106 }
Chris@16 107 template<class D>
Chris@16 108 BOOST_UBLAS_INLINE
Chris@16 109 sparse_vector_element &operator /= (const D &d) {
Chris@16 110 get_d ();
Chris@16 111 d_ /= d;
Chris@16 112 set (d_);
Chris@16 113 return *this;
Chris@16 114 }
Chris@16 115
Chris@16 116 // Comparison
Chris@16 117 template<class D>
Chris@16 118 BOOST_UBLAS_INLINE
Chris@16 119 bool operator == (const D &d) const {
Chris@16 120 get_d ();
Chris@16 121 return d_ == d;
Chris@16 122 }
Chris@16 123 template<class D>
Chris@16 124 BOOST_UBLAS_INLINE
Chris@16 125 bool operator != (const D &d) const {
Chris@16 126 get_d ();
Chris@16 127 return d_ != d;
Chris@16 128 }
Chris@16 129
Chris@16 130 // Conversion - weak link in proxy as d_ is not a perfect alias for the element
Chris@16 131 BOOST_UBLAS_INLINE
Chris@16 132 operator const_reference () const {
Chris@16 133 get_d ();
Chris@16 134 return d_;
Chris@16 135 }
Chris@16 136
Chris@16 137 // Conversion to reference - may be invalidated
Chris@16 138 BOOST_UBLAS_INLINE
Chris@16 139 value_type& ref () const {
Chris@16 140 const pointer p = (*this) ().find_element (i_);
Chris@16 141 if (!p)
Chris@16 142 return (*this) ().insert_element (i_, value_type/*zero*/());
Chris@16 143 else
Chris@16 144 return *p;
Chris@16 145 }
Chris@16 146
Chris@16 147 private:
Chris@16 148 size_type i_;
Chris@16 149 mutable value_type d_;
Chris@16 150 };
Chris@16 151
Chris@16 152 /*
Chris@16 153 * Generalise explicit reference access
Chris@16 154 */
Chris@16 155 namespace detail {
Chris@16 156 template <class R>
Chris@16 157 struct element_reference {
Chris@16 158 typedef R& reference;
Chris@16 159 static reference get_reference (reference r)
Chris@16 160 {
Chris@16 161 return r;
Chris@16 162 }
Chris@16 163 };
Chris@16 164 template <class V>
Chris@16 165 struct element_reference<sparse_vector_element<V> > {
Chris@16 166 typedef typename V::value_type& reference;
Chris@16 167 static reference get_reference (const sparse_vector_element<V>& sve)
Chris@16 168 {
Chris@16 169 return sve.ref ();
Chris@16 170 }
Chris@16 171 };
Chris@16 172 }
Chris@16 173 template <class VER>
Chris@16 174 typename detail::element_reference<VER>::reference ref (VER& ver) {
Chris@16 175 return detail::element_reference<VER>::get_reference (ver);
Chris@16 176 }
Chris@16 177 template <class VER>
Chris@16 178 typename detail::element_reference<VER>::reference ref (const VER& ver) {
Chris@16 179 return detail::element_reference<VER>::get_reference (ver);
Chris@16 180 }
Chris@16 181
Chris@16 182
Chris@16 183 template<class V>
Chris@16 184 struct type_traits<sparse_vector_element<V> > {
Chris@16 185 typedef typename V::value_type element_type;
Chris@16 186 typedef type_traits<sparse_vector_element<V> > self_type;
Chris@16 187 typedef typename type_traits<element_type>::value_type value_type;
Chris@16 188 typedef typename type_traits<element_type>::const_reference const_reference;
Chris@16 189 typedef sparse_vector_element<V> reference;
Chris@16 190 typedef typename type_traits<element_type>::real_type real_type;
Chris@16 191 typedef typename type_traits<element_type>::precision_type precision_type;
Chris@16 192
Chris@16 193 static const unsigned plus_complexity = type_traits<element_type>::plus_complexity;
Chris@16 194 static const unsigned multiplies_complexity = type_traits<element_type>::multiplies_complexity;
Chris@16 195
Chris@16 196 static
Chris@16 197 BOOST_UBLAS_INLINE
Chris@16 198 real_type real (const_reference t) {
Chris@16 199 return type_traits<element_type>::real (t);
Chris@16 200 }
Chris@16 201 static
Chris@16 202 BOOST_UBLAS_INLINE
Chris@16 203 real_type imag (const_reference t) {
Chris@16 204 return type_traits<element_type>::imag (t);
Chris@16 205 }
Chris@16 206 static
Chris@16 207 BOOST_UBLAS_INLINE
Chris@16 208 value_type conj (const_reference t) {
Chris@16 209 return type_traits<element_type>::conj (t);
Chris@16 210 }
Chris@16 211
Chris@16 212 static
Chris@16 213 BOOST_UBLAS_INLINE
Chris@16 214 real_type type_abs (const_reference t) {
Chris@16 215 return type_traits<element_type>::type_abs (t);
Chris@16 216 }
Chris@16 217 static
Chris@16 218 BOOST_UBLAS_INLINE
Chris@16 219 value_type type_sqrt (const_reference t) {
Chris@16 220 return type_traits<element_type>::type_sqrt (t);
Chris@16 221 }
Chris@16 222
Chris@16 223 static
Chris@16 224 BOOST_UBLAS_INLINE
Chris@16 225 real_type norm_1 (const_reference t) {
Chris@16 226 return type_traits<element_type>::norm_1 (t);
Chris@16 227 }
Chris@16 228 static
Chris@16 229 BOOST_UBLAS_INLINE
Chris@16 230 real_type norm_2 (const_reference t) {
Chris@16 231 return type_traits<element_type>::norm_2 (t);
Chris@16 232 }
Chris@16 233 static
Chris@16 234 BOOST_UBLAS_INLINE
Chris@16 235 real_type norm_inf (const_reference t) {
Chris@16 236 return type_traits<element_type>::norm_inf (t);
Chris@16 237 }
Chris@16 238
Chris@16 239 static
Chris@16 240 BOOST_UBLAS_INLINE
Chris@16 241 bool equals (const_reference t1, const_reference t2) {
Chris@16 242 return type_traits<element_type>::equals (t1, t2);
Chris@16 243 }
Chris@16 244 };
Chris@16 245
Chris@16 246 template<class V1, class T2>
Chris@16 247 struct promote_traits<sparse_vector_element<V1>, T2> {
Chris@16 248 typedef typename promote_traits<typename sparse_vector_element<V1>::value_type, T2>::promote_type promote_type;
Chris@16 249 };
Chris@16 250 template<class T1, class V2>
Chris@16 251 struct promote_traits<T1, sparse_vector_element<V2> > {
Chris@16 252 typedef typename promote_traits<T1, typename sparse_vector_element<V2>::value_type>::promote_type promote_type;
Chris@16 253 };
Chris@16 254 template<class V1, class V2>
Chris@16 255 struct promote_traits<sparse_vector_element<V1>, sparse_vector_element<V2> > {
Chris@16 256 typedef typename promote_traits<typename sparse_vector_element<V1>::value_type,
Chris@16 257 typename sparse_vector_element<V2>::value_type>::promote_type promote_type;
Chris@16 258 };
Chris@16 259
Chris@16 260 #endif
Chris@16 261
Chris@16 262
Chris@16 263 /** \brief Index map based sparse vector
Chris@16 264 *
Chris@16 265 * A sparse vector of values of type T of variable size. The sparse storage type A can be
Chris@16 266 * \c std::map<size_t, T> or \c map_array<size_t, T>. This means that only non-zero elements
Chris@16 267 * are effectively stored.
Chris@16 268 *
Chris@16 269 * For a \f$n\f$-dimensional sparse vector, and 0 <= i < n the non-zero elements \f$v_i\f$
Chris@16 270 * are mapped to consecutive elements of the associative container, i.e. for elements
Chris@16 271 * \f$k = v_{i_1}\f$ and \f$k + 1 = v_{i_2}\f$ of the container, holds \f$i_1 < i_2\f$.
Chris@16 272 *
Chris@16 273 * Supported parameters for the adapted array are \c map_array<std::size_t, T> and
Chris@16 274 * \c map_std<std::size_t, T>. The latter is equivalent to \c std::map<std::size_t, T>.
Chris@16 275 *
Chris@16 276 * \tparam T the type of object stored in the vector (like double, float, complex, etc...)
Chris@16 277 * \tparam A the type of Storage array
Chris@16 278 */
Chris@16 279 template<class T, class A>
Chris@16 280 class mapped_vector:
Chris@16 281 public vector_container<mapped_vector<T, A> > {
Chris@16 282
Chris@16 283 typedef T &true_reference;
Chris@16 284 typedef T *pointer;
Chris@16 285 typedef const T *const_pointer;
Chris@16 286 typedef mapped_vector<T, A> self_type;
Chris@16 287 public:
Chris@16 288 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
Chris@16 289 using vector_container<self_type>::operator ();
Chris@16 290 #endif
Chris@16 291 typedef typename A::size_type size_type;
Chris@16 292 typedef typename A::difference_type difference_type;
Chris@16 293 typedef T value_type;
Chris@16 294 typedef A array_type;
Chris@16 295 typedef const value_type &const_reference;
Chris@16 296 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
Chris@16 297 typedef typename detail::map_traits<A,T>::reference reference;
Chris@16 298 #else
Chris@16 299 typedef sparse_vector_element<self_type> reference;
Chris@16 300 #endif
Chris@16 301 typedef const vector_reference<const self_type> const_closure_type;
Chris@16 302 typedef vector_reference<self_type> closure_type;
Chris@16 303 typedef self_type vector_temporary_type;
Chris@16 304 typedef sparse_tag storage_category;
Chris@16 305
Chris@16 306 // Construction and destruction
Chris@16 307 BOOST_UBLAS_INLINE
Chris@16 308 mapped_vector ():
Chris@16 309 vector_container<self_type> (),
Chris@16 310 size_ (0), data_ () {}
Chris@16 311 BOOST_UBLAS_INLINE
Chris@16 312 mapped_vector (size_type size, size_type non_zeros = 0):
Chris@16 313 vector_container<self_type> (),
Chris@16 314 size_ (size), data_ () {
Chris@16 315 detail::map_reserve (data(), restrict_capacity (non_zeros));
Chris@16 316 }
Chris@16 317 BOOST_UBLAS_INLINE
Chris@16 318 mapped_vector (const mapped_vector &v):
Chris@16 319 vector_container<self_type> (),
Chris@16 320 size_ (v.size_), data_ (v.data_) {}
Chris@16 321 template<class AE>
Chris@16 322 BOOST_UBLAS_INLINE
Chris@16 323 mapped_vector (const vector_expression<AE> &ae, size_type non_zeros = 0):
Chris@16 324 vector_container<self_type> (),
Chris@16 325 size_ (ae ().size ()), data_ () {
Chris@16 326 detail::map_reserve (data(), restrict_capacity (non_zeros));
Chris@16 327 vector_assign<scalar_assign> (*this, ae);
Chris@16 328 }
Chris@16 329
Chris@16 330 // Accessors
Chris@16 331 BOOST_UBLAS_INLINE
Chris@16 332 size_type size () const {
Chris@16 333 return size_;
Chris@16 334 }
Chris@16 335 BOOST_UBLAS_INLINE
Chris@16 336 size_type nnz_capacity () const {
Chris@16 337 return detail::map_capacity (data ());
Chris@16 338 }
Chris@16 339 BOOST_UBLAS_INLINE
Chris@16 340 size_type nnz () const {
Chris@16 341 return data (). size ();
Chris@16 342 }
Chris@16 343
Chris@16 344 // Storage accessors
Chris@16 345 BOOST_UBLAS_INLINE
Chris@16 346 const array_type &data () const {
Chris@16 347 return data_;
Chris@16 348 }
Chris@16 349 BOOST_UBLAS_INLINE
Chris@16 350 array_type &data () {
Chris@16 351 return data_;
Chris@16 352 }
Chris@16 353
Chris@16 354 // Resizing
Chris@16 355 private:
Chris@16 356 BOOST_UBLAS_INLINE
Chris@16 357 size_type restrict_capacity (size_type non_zeros) const {
Chris@16 358 non_zeros = (std::min) (non_zeros, size_);
Chris@16 359 return non_zeros;
Chris@16 360 }
Chris@16 361 public:
Chris@16 362 BOOST_UBLAS_INLINE
Chris@16 363 void resize (size_type size, bool preserve = true) {
Chris@16 364 size_ = size;
Chris@16 365 if (preserve) {
Chris@16 366 data ().erase (data ().lower_bound(size_), data ().end());
Chris@16 367 }
Chris@16 368 else {
Chris@16 369 data ().clear ();
Chris@16 370 }
Chris@16 371 }
Chris@16 372
Chris@16 373 // Reserving
Chris@16 374 BOOST_UBLAS_INLINE
Chris@16 375 void reserve (size_type non_zeros = 0, bool preserve = true) {
Chris@16 376 detail::map_reserve (data (), restrict_capacity (non_zeros));
Chris@16 377 }
Chris@16 378
Chris@16 379 // Element support
Chris@16 380 BOOST_UBLAS_INLINE
Chris@16 381 pointer find_element (size_type i) {
Chris@16 382 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
Chris@16 383 }
Chris@16 384 BOOST_UBLAS_INLINE
Chris@16 385 const_pointer find_element (size_type i) const {
Chris@16 386 const_subiterator_type it (data ().find (i));
Chris@16 387 if (it == data ().end ())
Chris@16 388 return 0;
Chris@16 389 BOOST_UBLAS_CHECK ((*it).first == i, internal_logic ()); // broken map
Chris@16 390 return &(*it).second;
Chris@16 391 }
Chris@16 392
Chris@16 393 // Element access
Chris@16 394 BOOST_UBLAS_INLINE
Chris@16 395 const_reference operator () (size_type i) const {
Chris@16 396 BOOST_UBLAS_CHECK (i < size_, bad_index ());
Chris@16 397 const_subiterator_type it (data ().find (i));
Chris@16 398 if (it == data ().end ())
Chris@16 399 return zero_;
Chris@16 400 BOOST_UBLAS_CHECK ((*it).first == i, internal_logic ()); // broken map
Chris@16 401 return (*it).second;
Chris@16 402 }
Chris@16 403 BOOST_UBLAS_INLINE
Chris@16 404 true_reference ref (size_type i) {
Chris@16 405 BOOST_UBLAS_CHECK (i < size_, bad_index ());
Chris@16 406 std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (i, value_type/*zero*/())));
Chris@16 407 BOOST_UBLAS_CHECK ((ii.first)->first == i, internal_logic ()); // broken map
Chris@16 408 return (ii.first)->second;
Chris@16 409 }
Chris@16 410 BOOST_UBLAS_INLINE
Chris@16 411 reference operator () (size_type i) {
Chris@16 412 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
Chris@16 413 return ref (i);
Chris@16 414 #else
Chris@16 415 BOOST_UBLAS_CHECK (i < size_, bad_index ());
Chris@16 416 return reference (*this, i);
Chris@16 417 #endif
Chris@16 418 }
Chris@16 419
Chris@16 420 BOOST_UBLAS_INLINE
Chris@16 421 const_reference operator [] (size_type i) const {
Chris@16 422 return (*this) (i);
Chris@16 423 }
Chris@16 424 BOOST_UBLAS_INLINE
Chris@16 425 reference operator [] (size_type i) {
Chris@16 426 return (*this) (i);
Chris@16 427 }
Chris@16 428
Chris@16 429 // Element assignment
Chris@16 430 BOOST_UBLAS_INLINE
Chris@16 431 true_reference insert_element (size_type i, const_reference t) {
Chris@16 432 std::pair<subiterator_type, bool> ii = data ().insert (typename array_type::value_type (i, t));
Chris@16 433 BOOST_UBLAS_CHECK (ii.second, bad_index ()); // duplicate element
Chris@16 434 BOOST_UBLAS_CHECK ((ii.first)->first == i, internal_logic ()); // broken map
Chris@16 435 if (!ii.second) // existing element
Chris@16 436 (ii.first)->second = t;
Chris@16 437 return (ii.first)->second;
Chris@16 438 }
Chris@16 439 BOOST_UBLAS_INLINE
Chris@16 440 void erase_element (size_type i) {
Chris@16 441 subiterator_type it = data ().find (i);
Chris@16 442 if (it == data ().end ())
Chris@16 443 return;
Chris@16 444 data ().erase (it);
Chris@16 445 }
Chris@16 446
Chris@16 447 // Zeroing
Chris@16 448 BOOST_UBLAS_INLINE
Chris@16 449 void clear () {
Chris@16 450 data ().clear ();
Chris@16 451 }
Chris@16 452
Chris@16 453 // Assignment
Chris@16 454 BOOST_UBLAS_INLINE
Chris@16 455 mapped_vector &operator = (const mapped_vector &v) {
Chris@16 456 if (this != &v) {
Chris@16 457 size_ = v.size_;
Chris@16 458 data () = v.data ();
Chris@16 459 }
Chris@16 460 return *this;
Chris@16 461 }
Chris@16 462 template<class C> // Container assignment without temporary
Chris@16 463 BOOST_UBLAS_INLINE
Chris@16 464 mapped_vector &operator = (const vector_container<C> &v) {
Chris@16 465 resize (v ().size (), false);
Chris@16 466 assign (v);
Chris@16 467 return *this;
Chris@16 468 }
Chris@16 469 BOOST_UBLAS_INLINE
Chris@16 470 mapped_vector &assign_temporary (mapped_vector &v) {
Chris@16 471 swap (v);
Chris@16 472 return *this;
Chris@16 473 }
Chris@16 474 template<class AE>
Chris@16 475 BOOST_UBLAS_INLINE
Chris@16 476 mapped_vector &operator = (const vector_expression<AE> &ae) {
Chris@16 477 self_type temporary (ae, detail::map_capacity (data()));
Chris@16 478 return assign_temporary (temporary);
Chris@16 479 }
Chris@16 480 template<class AE>
Chris@16 481 BOOST_UBLAS_INLINE
Chris@16 482 mapped_vector &assign (const vector_expression<AE> &ae) {
Chris@16 483 vector_assign<scalar_assign> (*this, ae);
Chris@16 484 return *this;
Chris@16 485 }
Chris@16 486
Chris@16 487 // Computed assignment
Chris@16 488 template<class AE>
Chris@16 489 BOOST_UBLAS_INLINE
Chris@16 490 mapped_vector &operator += (const vector_expression<AE> &ae) {
Chris@16 491 self_type temporary (*this + ae, detail::map_capacity (data()));
Chris@16 492 return assign_temporary (temporary);
Chris@16 493 }
Chris@16 494 template<class C> // Container assignment without temporary
Chris@16 495 BOOST_UBLAS_INLINE
Chris@16 496 mapped_vector &operator += (const vector_container<C> &v) {
Chris@16 497 plus_assign (v);
Chris@16 498 return *this;
Chris@16 499 }
Chris@16 500 template<class AE>
Chris@16 501 BOOST_UBLAS_INLINE
Chris@16 502 mapped_vector &plus_assign (const vector_expression<AE> &ae) {
Chris@16 503 vector_assign<scalar_plus_assign> (*this, ae);
Chris@16 504 return *this;
Chris@16 505 }
Chris@16 506 template<class AE>
Chris@16 507 BOOST_UBLAS_INLINE
Chris@16 508 mapped_vector &operator -= (const vector_expression<AE> &ae) {
Chris@16 509 self_type temporary (*this - ae, detail::map_capacity (data()));
Chris@16 510 return assign_temporary (temporary);
Chris@16 511 }
Chris@16 512 template<class C> // Container assignment without temporary
Chris@16 513 BOOST_UBLAS_INLINE
Chris@16 514 mapped_vector &operator -= (const vector_container<C> &v) {
Chris@16 515 minus_assign (v);
Chris@16 516 return *this;
Chris@16 517 }
Chris@16 518 template<class AE>
Chris@16 519 BOOST_UBLAS_INLINE
Chris@16 520 mapped_vector &minus_assign (const vector_expression<AE> &ae) {
Chris@16 521 vector_assign<scalar_minus_assign> (*this, ae);
Chris@16 522 return *this;
Chris@16 523 }
Chris@16 524 template<class AT>
Chris@16 525 BOOST_UBLAS_INLINE
Chris@16 526 mapped_vector &operator *= (const AT &at) {
Chris@16 527 vector_assign_scalar<scalar_multiplies_assign> (*this, at);
Chris@16 528 return *this;
Chris@16 529 }
Chris@16 530 template<class AT>
Chris@16 531 BOOST_UBLAS_INLINE
Chris@16 532 mapped_vector &operator /= (const AT &at) {
Chris@16 533 vector_assign_scalar<scalar_divides_assign> (*this, at);
Chris@16 534 return *this;
Chris@16 535 }
Chris@16 536
Chris@16 537 // Swapping
Chris@16 538 BOOST_UBLAS_INLINE
Chris@16 539 void swap (mapped_vector &v) {
Chris@16 540 if (this != &v) {
Chris@16 541 std::swap (size_, v.size_);
Chris@16 542 data ().swap (v.data ());
Chris@16 543 }
Chris@16 544 }
Chris@16 545 BOOST_UBLAS_INLINE
Chris@16 546 friend void swap (mapped_vector &v1, mapped_vector &v2) {
Chris@16 547 v1.swap (v2);
Chris@16 548 }
Chris@16 549
Chris@16 550 // Iterator types
Chris@16 551 private:
Chris@16 552 // Use storage iterator
Chris@16 553 typedef typename A::const_iterator const_subiterator_type;
Chris@16 554 typedef typename A::iterator subiterator_type;
Chris@16 555
Chris@16 556 BOOST_UBLAS_INLINE
Chris@16 557 true_reference at_element (size_type i) {
Chris@16 558 BOOST_UBLAS_CHECK (i < size_, bad_index ());
Chris@16 559 subiterator_type it (data ().find (i));
Chris@16 560 BOOST_UBLAS_CHECK (it != data ().end(), bad_index ());
Chris@16 561 BOOST_UBLAS_CHECK ((*it).first == i, internal_logic ()); // broken map
Chris@16 562 return it->second;
Chris@16 563 }
Chris@16 564
Chris@16 565 public:
Chris@16 566 class const_iterator;
Chris@16 567 class iterator;
Chris@16 568
Chris@16 569 // Element lookup
Chris@16 570 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 571 const_iterator find (size_type i) const {
Chris@16 572 return const_iterator (*this, data ().lower_bound (i));
Chris@16 573 }
Chris@16 574 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 575 iterator find (size_type i) {
Chris@16 576 return iterator (*this, data ().lower_bound (i));
Chris@16 577 }
Chris@16 578
Chris@16 579
Chris@16 580 class const_iterator:
Chris@16 581 public container_const_reference<mapped_vector>,
Chris@16 582 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 583 const_iterator, value_type> {
Chris@16 584 public:
Chris@16 585 typedef typename mapped_vector::value_type value_type;
Chris@16 586 typedef typename mapped_vector::difference_type difference_type;
Chris@16 587 typedef typename mapped_vector::const_reference reference;
Chris@16 588 typedef const typename mapped_vector::pointer pointer;
Chris@16 589
Chris@16 590 // Construction and destruction
Chris@16 591 BOOST_UBLAS_INLINE
Chris@16 592 const_iterator ():
Chris@16 593 container_const_reference<self_type> (), it_ () {}
Chris@16 594 BOOST_UBLAS_INLINE
Chris@16 595 const_iterator (const self_type &v, const const_subiterator_type &it):
Chris@16 596 container_const_reference<self_type> (v), it_ (it) {}
Chris@16 597 BOOST_UBLAS_INLINE
Chris@16 598 const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
Chris@16 599 container_const_reference<self_type> (it ()), it_ (it.it_) {}
Chris@16 600
Chris@16 601 // Arithmetic
Chris@16 602 BOOST_UBLAS_INLINE
Chris@16 603 const_iterator &operator ++ () {
Chris@16 604 ++ it_;
Chris@16 605 return *this;
Chris@16 606 }
Chris@16 607 BOOST_UBLAS_INLINE
Chris@16 608 const_iterator &operator -- () {
Chris@16 609 -- it_;
Chris@16 610 return *this;
Chris@16 611 }
Chris@16 612
Chris@16 613 // Dereference
Chris@16 614 BOOST_UBLAS_INLINE
Chris@16 615 const_reference operator * () const {
Chris@16 616 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
Chris@16 617 return (*it_).second;
Chris@16 618 }
Chris@16 619
Chris@16 620 // Index
Chris@16 621 BOOST_UBLAS_INLINE
Chris@16 622 size_type index () const {
Chris@16 623 BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
Chris@16 624 BOOST_UBLAS_CHECK ((*it_).first < (*this) ().size (), bad_index ());
Chris@16 625 return (*it_).first;
Chris@16 626 }
Chris@16 627
Chris@16 628 // Assignment
Chris@16 629 BOOST_UBLAS_INLINE
Chris@16 630 const_iterator &operator = (const const_iterator &it) {
Chris@16 631 container_const_reference<self_type>::assign (&it ());
Chris@16 632 it_ = it.it_;
Chris@16 633 return *this;
Chris@16 634 }
Chris@16 635
Chris@16 636 // Comparison
Chris@16 637 BOOST_UBLAS_INLINE
Chris@16 638 bool operator == (const const_iterator &it) const {
Chris@16 639 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 640 return it_ == it.it_;
Chris@16 641 }
Chris@16 642
Chris@16 643 private:
Chris@16 644 const_subiterator_type it_;
Chris@16 645 };
Chris@16 646
Chris@16 647 BOOST_UBLAS_INLINE
Chris@16 648 const_iterator begin () const {
Chris@16 649 return const_iterator (*this, data ().begin ());
Chris@16 650 }
Chris@16 651 BOOST_UBLAS_INLINE
Chris@101 652 const_iterator cbegin () const {
Chris@101 653 return begin ();
Chris@101 654 }
Chris@101 655 BOOST_UBLAS_INLINE
Chris@16 656 const_iterator end () const {
Chris@16 657 return const_iterator (*this, data ().end ());
Chris@16 658 }
Chris@101 659 BOOST_UBLAS_INLINE
Chris@101 660 const_iterator cend () const {
Chris@101 661 return end ();
Chris@101 662 }
Chris@16 663
Chris@16 664 class iterator:
Chris@16 665 public container_reference<mapped_vector>,
Chris@16 666 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 667 iterator, value_type> {
Chris@16 668 public:
Chris@16 669 typedef typename mapped_vector::value_type value_type;
Chris@16 670 typedef typename mapped_vector::difference_type difference_type;
Chris@16 671 typedef typename mapped_vector::true_reference reference;
Chris@16 672 typedef typename mapped_vector::pointer pointer;
Chris@16 673
Chris@16 674 // Construction and destruction
Chris@16 675 BOOST_UBLAS_INLINE
Chris@16 676 iterator ():
Chris@16 677 container_reference<self_type> (), it_ () {}
Chris@16 678 BOOST_UBLAS_INLINE
Chris@16 679 iterator (self_type &v, const subiterator_type &it):
Chris@16 680 container_reference<self_type> (v), it_ (it) {}
Chris@16 681
Chris@16 682 // Arithmetic
Chris@16 683 BOOST_UBLAS_INLINE
Chris@16 684 iterator &operator ++ () {
Chris@16 685 ++ it_;
Chris@16 686 return *this;
Chris@16 687 }
Chris@16 688 BOOST_UBLAS_INLINE
Chris@16 689 iterator &operator -- () {
Chris@16 690 -- it_;
Chris@16 691 return *this;
Chris@16 692 }
Chris@16 693
Chris@16 694 // Dereference
Chris@16 695 BOOST_UBLAS_INLINE
Chris@16 696 reference operator * () const {
Chris@16 697 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
Chris@16 698 return (*it_).second;
Chris@16 699 }
Chris@16 700
Chris@16 701 // Index
Chris@16 702 BOOST_UBLAS_INLINE
Chris@16 703 size_type index () const {
Chris@16 704 BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
Chris@16 705 BOOST_UBLAS_CHECK ((*it_).first < (*this) ().size (), bad_index ());
Chris@16 706 return (*it_).first;
Chris@16 707 }
Chris@16 708
Chris@16 709 // Assignment
Chris@16 710 BOOST_UBLAS_INLINE
Chris@16 711 iterator &operator = (const iterator &it) {
Chris@16 712 container_reference<self_type>::assign (&it ());
Chris@16 713 it_ = it.it_;
Chris@16 714 return *this;
Chris@16 715 }
Chris@16 716
Chris@16 717 // Comparison
Chris@16 718 BOOST_UBLAS_INLINE
Chris@16 719 bool operator == (const iterator &it) const {
Chris@16 720 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 721 return it_ == it.it_;
Chris@16 722 }
Chris@16 723
Chris@16 724 private:
Chris@16 725 subiterator_type it_;
Chris@16 726
Chris@16 727 friend class const_iterator;
Chris@16 728 };
Chris@16 729
Chris@16 730 BOOST_UBLAS_INLINE
Chris@16 731 iterator begin () {
Chris@16 732 return iterator (*this, data ().begin ());
Chris@16 733 }
Chris@16 734 BOOST_UBLAS_INLINE
Chris@16 735 iterator end () {
Chris@16 736 return iterator (*this, data ().end ());
Chris@16 737 }
Chris@16 738
Chris@16 739 // Reverse iterator
Chris@16 740 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
Chris@16 741 typedef reverse_iterator_base<iterator> reverse_iterator;
Chris@16 742
Chris@16 743 BOOST_UBLAS_INLINE
Chris@16 744 const_reverse_iterator rbegin () const {
Chris@16 745 return const_reverse_iterator (end ());
Chris@16 746 }
Chris@16 747 BOOST_UBLAS_INLINE
Chris@101 748 const_reverse_iterator crbegin () const {
Chris@101 749 return rbegin ();
Chris@101 750 }
Chris@101 751 BOOST_UBLAS_INLINE
Chris@16 752 const_reverse_iterator rend () const {
Chris@16 753 return const_reverse_iterator (begin ());
Chris@16 754 }
Chris@16 755 BOOST_UBLAS_INLINE
Chris@101 756 const_reverse_iterator crend () const {
Chris@101 757 return rend ();
Chris@101 758 }
Chris@101 759 BOOST_UBLAS_INLINE
Chris@16 760 reverse_iterator rbegin () {
Chris@16 761 return reverse_iterator (end ());
Chris@16 762 }
Chris@16 763 BOOST_UBLAS_INLINE
Chris@16 764 reverse_iterator rend () {
Chris@16 765 return reverse_iterator (begin ());
Chris@16 766 }
Chris@16 767
Chris@16 768 // Serialization
Chris@16 769 template<class Archive>
Chris@16 770 void serialize(Archive & ar, const unsigned int /* file_version */){
Chris@16 771 serialization::collection_size_type s (size_);
Chris@16 772 ar & serialization::make_nvp("size",s);
Chris@16 773 if (Archive::is_loading::value) {
Chris@16 774 size_ = s;
Chris@16 775 }
Chris@16 776 ar & serialization::make_nvp("data", data_);
Chris@16 777 }
Chris@16 778
Chris@16 779 private:
Chris@16 780 size_type size_;
Chris@16 781 array_type data_;
Chris@16 782 static const value_type zero_;
Chris@16 783 };
Chris@16 784
Chris@16 785 template<class T, class A>
Chris@16 786 const typename mapped_vector<T, A>::value_type mapped_vector<T, A>::zero_ = value_type/*zero*/();
Chris@16 787
Chris@16 788
Chris@16 789 // Thanks to Kresimir Fresl for extending this to cover different index bases.
Chris@16 790
Chris@16 791 /** \brief Compressed array based sparse vector
Chris@16 792 *
Chris@16 793 * a sparse vector of values of type T of variable size. The non zero values are stored as
Chris@16 794 * two seperate arrays: an index array and a value array. The index array is always sorted
Chris@16 795 * and there is at most one entry for each index. Inserting an element can be time consuming.
Chris@16 796 * If the vector contains a few zero entries, then it is better to have a normal vector.
Chris@16 797 * If the vector has a very high dimension with a few non-zero values, then this vector is
Chris@16 798 * very memory efficient (at the cost of a few more computations).
Chris@16 799 *
Chris@16 800 * For a \f$n\f$-dimensional compressed vector and \f$0 \leq i < n\f$ the non-zero elements
Chris@16 801 * \f$v_i\f$ are mapped to consecutive elements of the index and value container, i.e. for
Chris@16 802 * elements \f$k = v_{i_1}\f$ and \f$k + 1 = v_{i_2}\f$ of these containers holds \f$i_1 < i_2\f$.
Chris@16 803 *
Chris@16 804 * Supported parameters for the adapted array (indices and values) are \c unbounded_array<> ,
Chris@16 805 * \c bounded_array<> and \c std::vector<>.
Chris@16 806 *
Chris@16 807 * \tparam T the type of object stored in the vector (like double, float, complex, etc...)
Chris@16 808 * \tparam IB the index base of the compressed vector. Default is 0. Other supported value is 1
Chris@16 809 * \tparam IA the type of adapted array for indices. Default is \c unbounded_array<std::size_t>
Chris@16 810 * \tparam TA the type of adapted array for values. Default is unbounded_array<T>
Chris@16 811 */
Chris@16 812 template<class T, std::size_t IB, class IA, class TA>
Chris@16 813 class compressed_vector:
Chris@16 814 public vector_container<compressed_vector<T, IB, IA, TA> > {
Chris@16 815
Chris@16 816 typedef T &true_reference;
Chris@16 817 typedef T *pointer;
Chris@16 818 typedef const T *const_pointer;
Chris@16 819 typedef compressed_vector<T, IB, IA, TA> self_type;
Chris@16 820 public:
Chris@16 821 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
Chris@16 822 using vector_container<self_type>::operator ();
Chris@16 823 #endif
Chris@16 824 // ISSUE require type consistency check
Chris@16 825 // is_convertable (IA::size_type, TA::size_type)
Chris@16 826 typedef typename IA::value_type size_type;
Chris@16 827 typedef typename IA::difference_type difference_type;
Chris@16 828 typedef T value_type;
Chris@16 829 typedef const T &const_reference;
Chris@16 830 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
Chris@16 831 typedef T &reference;
Chris@16 832 #else
Chris@16 833 typedef sparse_vector_element<self_type> reference;
Chris@16 834 #endif
Chris@16 835 typedef IA index_array_type;
Chris@16 836 typedef TA value_array_type;
Chris@16 837 typedef const vector_reference<const self_type> const_closure_type;
Chris@16 838 typedef vector_reference<self_type> closure_type;
Chris@16 839 typedef self_type vector_temporary_type;
Chris@16 840 typedef sparse_tag storage_category;
Chris@16 841
Chris@16 842 // Construction and destruction
Chris@16 843 BOOST_UBLAS_INLINE
Chris@16 844 compressed_vector ():
Chris@16 845 vector_container<self_type> (),
Chris@16 846 size_ (0), capacity_ (restrict_capacity (0)), filled_ (0),
Chris@16 847 index_data_ (capacity_), value_data_ (capacity_) {
Chris@16 848 storage_invariants ();
Chris@16 849 }
Chris@16 850 explicit BOOST_UBLAS_INLINE
Chris@16 851 compressed_vector (size_type size, size_type non_zeros = 0):
Chris@16 852 vector_container<self_type> (),
Chris@16 853 size_ (size), capacity_ (restrict_capacity (non_zeros)), filled_ (0),
Chris@16 854 index_data_ (capacity_), value_data_ (capacity_) {
Chris@16 855 storage_invariants ();
Chris@16 856 }
Chris@16 857 BOOST_UBLAS_INLINE
Chris@16 858 compressed_vector (const compressed_vector &v):
Chris@16 859 vector_container<self_type> (),
Chris@16 860 size_ (v.size_), capacity_ (v.capacity_), filled_ (v.filled_),
Chris@16 861 index_data_ (v.index_data_), value_data_ (v.value_data_) {
Chris@16 862 storage_invariants ();
Chris@16 863 }
Chris@16 864 template<class AE>
Chris@16 865 BOOST_UBLAS_INLINE
Chris@16 866 compressed_vector (const vector_expression<AE> &ae, size_type non_zeros = 0):
Chris@16 867 vector_container<self_type> (),
Chris@16 868 size_ (ae ().size ()), capacity_ (restrict_capacity (non_zeros)), filled_ (0),
Chris@16 869 index_data_ (capacity_), value_data_ (capacity_) {
Chris@16 870 storage_invariants ();
Chris@16 871 vector_assign<scalar_assign> (*this, ae);
Chris@16 872 }
Chris@16 873
Chris@16 874 // Accessors
Chris@16 875 BOOST_UBLAS_INLINE
Chris@16 876 size_type size () const {
Chris@16 877 return size_;
Chris@16 878 }
Chris@16 879 BOOST_UBLAS_INLINE
Chris@16 880 size_type nnz_capacity () const {
Chris@16 881 return capacity_;
Chris@16 882 }
Chris@16 883 BOOST_UBLAS_INLINE
Chris@16 884 size_type nnz () const {
Chris@16 885 return filled_;
Chris@16 886 }
Chris@16 887
Chris@16 888 // Storage accessors
Chris@16 889 BOOST_UBLAS_INLINE
Chris@16 890 static size_type index_base () {
Chris@16 891 return IB;
Chris@16 892 }
Chris@16 893 BOOST_UBLAS_INLINE
Chris@16 894 typename index_array_type::size_type filled () const {
Chris@16 895 return filled_;
Chris@16 896 }
Chris@16 897 BOOST_UBLAS_INLINE
Chris@16 898 const index_array_type &index_data () const {
Chris@16 899 return index_data_;
Chris@16 900 }
Chris@16 901 BOOST_UBLAS_INLINE
Chris@16 902 const value_array_type &value_data () const {
Chris@16 903 return value_data_;
Chris@16 904 }
Chris@16 905 BOOST_UBLAS_INLINE
Chris@16 906 void set_filled (const typename index_array_type::size_type & filled) {
Chris@16 907 filled_ = filled;
Chris@16 908 storage_invariants ();
Chris@16 909 }
Chris@16 910 BOOST_UBLAS_INLINE
Chris@16 911 index_array_type &index_data () {
Chris@16 912 return index_data_;
Chris@16 913 }
Chris@16 914 BOOST_UBLAS_INLINE
Chris@16 915 value_array_type &value_data () {
Chris@16 916 return value_data_;
Chris@16 917 }
Chris@16 918
Chris@16 919 // Resizing
Chris@16 920 private:
Chris@16 921 BOOST_UBLAS_INLINE
Chris@16 922 size_type restrict_capacity (size_type non_zeros) const {
Chris@16 923 non_zeros = (std::max) (non_zeros, size_type (1));
Chris@16 924 non_zeros = (std::min) (non_zeros, size_);
Chris@16 925 return non_zeros;
Chris@16 926 }
Chris@16 927 public:
Chris@16 928 BOOST_UBLAS_INLINE
Chris@16 929 void resize (size_type size, bool preserve = true) {
Chris@16 930 size_ = size;
Chris@16 931 capacity_ = restrict_capacity (capacity_);
Chris@16 932 if (preserve) {
Chris@16 933 index_data_. resize (capacity_, size_type ());
Chris@16 934 value_data_. resize (capacity_, value_type ());
Chris@16 935 filled_ = (std::min) (capacity_, filled_);
Chris@16 936 while ((filled_ > 0) && (zero_based(index_data_[filled_ - 1]) >= size)) {
Chris@16 937 --filled_;
Chris@16 938 }
Chris@16 939 }
Chris@16 940 else {
Chris@16 941 index_data_. resize (capacity_);
Chris@16 942 value_data_. resize (capacity_);
Chris@16 943 filled_ = 0;
Chris@16 944 }
Chris@16 945 storage_invariants ();
Chris@16 946 }
Chris@16 947
Chris@16 948 // Reserving
Chris@16 949 BOOST_UBLAS_INLINE
Chris@16 950 void reserve (size_type non_zeros, bool preserve = true) {
Chris@16 951 capacity_ = restrict_capacity (non_zeros);
Chris@16 952 if (preserve) {
Chris@16 953 index_data_. resize (capacity_, size_type ());
Chris@16 954 value_data_. resize (capacity_, value_type ());
Chris@16 955 filled_ = (std::min) (capacity_, filled_);
Chris@16 956 }
Chris@16 957 else {
Chris@16 958 index_data_. resize (capacity_);
Chris@16 959 value_data_. resize (capacity_);
Chris@16 960 filled_ = 0;
Chris@16 961 }
Chris@16 962 storage_invariants ();
Chris@16 963 }
Chris@16 964
Chris@16 965 // Element support
Chris@16 966 BOOST_UBLAS_INLINE
Chris@16 967 pointer find_element (size_type i) {
Chris@16 968 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
Chris@16 969 }
Chris@16 970 BOOST_UBLAS_INLINE
Chris@16 971 const_pointer find_element (size_type i) const {
Chris@16 972 const_subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 973 if (it == index_data_.begin () + filled_ || *it != k_based (i))
Chris@16 974 return 0;
Chris@16 975 return &value_data_ [it - index_data_.begin ()];
Chris@16 976 }
Chris@16 977
Chris@16 978 // Element access
Chris@16 979 BOOST_UBLAS_INLINE
Chris@16 980 const_reference operator () (size_type i) const {
Chris@16 981 BOOST_UBLAS_CHECK (i < size_, bad_index ());
Chris@16 982 const_subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 983 if (it == index_data_.begin () + filled_ || *it != k_based (i))
Chris@16 984 return zero_;
Chris@16 985 return value_data_ [it - index_data_.begin ()];
Chris@16 986 }
Chris@16 987 BOOST_UBLAS_INLINE
Chris@16 988 true_reference ref (size_type i) {
Chris@16 989 BOOST_UBLAS_CHECK (i < size_, bad_index ());
Chris@16 990 subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 991 if (it == index_data_.begin () + filled_ || *it != k_based (i))
Chris@16 992 return insert_element (i, value_type/*zero*/());
Chris@16 993 else
Chris@16 994 return value_data_ [it - index_data_.begin ()];
Chris@16 995 }
Chris@16 996 BOOST_UBLAS_INLINE
Chris@16 997 reference operator () (size_type i) {
Chris@16 998 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
Chris@16 999 return ref (i) ;
Chris@16 1000 #else
Chris@16 1001 BOOST_UBLAS_CHECK (i < size_, bad_index ());
Chris@16 1002 return reference (*this, i);
Chris@16 1003 #endif
Chris@16 1004 }
Chris@16 1005
Chris@16 1006 BOOST_UBLAS_INLINE
Chris@16 1007 const_reference operator [] (size_type i) const {
Chris@16 1008 return (*this) (i);
Chris@16 1009 }
Chris@16 1010 BOOST_UBLAS_INLINE
Chris@16 1011 reference operator [] (size_type i) {
Chris@16 1012 return (*this) (i);
Chris@16 1013 }
Chris@16 1014
Chris@16 1015 // Element assignment
Chris@16 1016 BOOST_UBLAS_INLINE
Chris@16 1017 true_reference insert_element (size_type i, const_reference t) {
Chris@16 1018 BOOST_UBLAS_CHECK (!find_element (i), bad_index ()); // duplicate element
Chris@16 1019 if (filled_ >= capacity_)
Chris@16 1020 reserve (2 * capacity_, true);
Chris@16 1021 subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 1022 // ISSUE max_capacity limit due to difference_type
Chris@16 1023 typename std::iterator_traits<subiterator_type>::difference_type n = it - index_data_.begin ();
Chris@16 1024 BOOST_UBLAS_CHECK (filled_ == 0 || filled_ == typename index_array_type::size_type (n) || *it != k_based (i), internal_logic ()); // duplicate found by lower_bound
Chris@16 1025 ++ filled_;
Chris@16 1026 it = index_data_.begin () + n;
Chris@16 1027 std::copy_backward (it, index_data_.begin () + filled_ - 1, index_data_.begin () + filled_);
Chris@16 1028 *it = k_based (i);
Chris@16 1029 typename value_array_type::iterator itt (value_data_.begin () + n);
Chris@16 1030 std::copy_backward (itt, value_data_.begin () + filled_ - 1, value_data_.begin () + filled_);
Chris@16 1031 *itt = t;
Chris@16 1032 storage_invariants ();
Chris@16 1033 return *itt;
Chris@16 1034 }
Chris@16 1035 BOOST_UBLAS_INLINE
Chris@16 1036 void erase_element (size_type i) {
Chris@16 1037 subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 1038 typename std::iterator_traits<subiterator_type>::difference_type n = it - index_data_.begin ();
Chris@16 1039 if (filled_ > typename index_array_type::size_type (n) && *it == k_based (i)) {
Chris@16 1040 std::copy (it + 1, index_data_.begin () + filled_, it);
Chris@16 1041 typename value_array_type::iterator itt (value_data_.begin () + n);
Chris@16 1042 std::copy (itt + 1, value_data_.begin () + filled_, itt);
Chris@16 1043 -- filled_;
Chris@16 1044 }
Chris@16 1045 storage_invariants ();
Chris@16 1046 }
Chris@16 1047
Chris@16 1048 // Zeroing
Chris@16 1049 BOOST_UBLAS_INLINE
Chris@16 1050 void clear () {
Chris@16 1051 filled_ = 0;
Chris@16 1052 storage_invariants ();
Chris@16 1053 }
Chris@16 1054
Chris@16 1055 // Assignment
Chris@16 1056 BOOST_UBLAS_INLINE
Chris@16 1057 compressed_vector &operator = (const compressed_vector &v) {
Chris@16 1058 if (this != &v) {
Chris@16 1059 size_ = v.size_;
Chris@16 1060 capacity_ = v.capacity_;
Chris@16 1061 filled_ = v.filled_;
Chris@16 1062 index_data_ = v.index_data_;
Chris@16 1063 value_data_ = v.value_data_;
Chris@16 1064 }
Chris@16 1065 storage_invariants ();
Chris@16 1066 return *this;
Chris@16 1067 }
Chris@16 1068 template<class C> // Container assignment without temporary
Chris@16 1069 BOOST_UBLAS_INLINE
Chris@16 1070 compressed_vector &operator = (const vector_container<C> &v) {
Chris@16 1071 resize (v ().size (), false);
Chris@16 1072 assign (v);
Chris@16 1073 return *this;
Chris@16 1074 }
Chris@16 1075 BOOST_UBLAS_INLINE
Chris@16 1076 compressed_vector &assign_temporary (compressed_vector &v) {
Chris@16 1077 swap (v);
Chris@16 1078 return *this;
Chris@16 1079 }
Chris@16 1080 template<class AE>
Chris@16 1081 BOOST_UBLAS_INLINE
Chris@16 1082 compressed_vector &operator = (const vector_expression<AE> &ae) {
Chris@16 1083 self_type temporary (ae, capacity_);
Chris@16 1084 return assign_temporary (temporary);
Chris@16 1085 }
Chris@16 1086 template<class AE>
Chris@16 1087 BOOST_UBLAS_INLINE
Chris@16 1088 compressed_vector &assign (const vector_expression<AE> &ae) {
Chris@16 1089 vector_assign<scalar_assign> (*this, ae);
Chris@16 1090 return *this;
Chris@16 1091 }
Chris@16 1092
Chris@16 1093 // Computed assignment
Chris@16 1094 template<class AE>
Chris@16 1095 BOOST_UBLAS_INLINE
Chris@16 1096 compressed_vector &operator += (const vector_expression<AE> &ae) {
Chris@16 1097 self_type temporary (*this + ae, capacity_);
Chris@16 1098 return assign_temporary (temporary);
Chris@16 1099 }
Chris@16 1100 template<class C> // Container assignment without temporary
Chris@16 1101 BOOST_UBLAS_INLINE
Chris@16 1102 compressed_vector &operator += (const vector_container<C> &v) {
Chris@16 1103 plus_assign (v);
Chris@16 1104 return *this;
Chris@16 1105 }
Chris@16 1106 template<class AE>
Chris@16 1107 BOOST_UBLAS_INLINE
Chris@16 1108 compressed_vector &plus_assign (const vector_expression<AE> &ae) {
Chris@16 1109 vector_assign<scalar_plus_assign> (*this, ae);
Chris@16 1110 return *this;
Chris@16 1111 }
Chris@16 1112 template<class AE>
Chris@16 1113 BOOST_UBLAS_INLINE
Chris@16 1114 compressed_vector &operator -= (const vector_expression<AE> &ae) {
Chris@16 1115 self_type temporary (*this - ae, capacity_);
Chris@16 1116 return assign_temporary (temporary);
Chris@16 1117 }
Chris@16 1118 template<class C> // Container assignment without temporary
Chris@16 1119 BOOST_UBLAS_INLINE
Chris@16 1120 compressed_vector &operator -= (const vector_container<C> &v) {
Chris@16 1121 minus_assign (v);
Chris@16 1122 return *this;
Chris@16 1123 }
Chris@16 1124 template<class AE>
Chris@16 1125 BOOST_UBLAS_INLINE
Chris@16 1126 compressed_vector &minus_assign (const vector_expression<AE> &ae) {
Chris@16 1127 vector_assign<scalar_minus_assign> (*this, ae);
Chris@16 1128 return *this;
Chris@16 1129 }
Chris@16 1130 template<class AT>
Chris@16 1131 BOOST_UBLAS_INLINE
Chris@16 1132 compressed_vector &operator *= (const AT &at) {
Chris@16 1133 vector_assign_scalar<scalar_multiplies_assign> (*this, at);
Chris@16 1134 return *this;
Chris@16 1135 }
Chris@16 1136 template<class AT>
Chris@16 1137 BOOST_UBLAS_INLINE
Chris@16 1138 compressed_vector &operator /= (const AT &at) {
Chris@16 1139 vector_assign_scalar<scalar_divides_assign> (*this, at);
Chris@16 1140 return *this;
Chris@16 1141 }
Chris@16 1142
Chris@16 1143 // Swapping
Chris@16 1144 BOOST_UBLAS_INLINE
Chris@16 1145 void swap (compressed_vector &v) {
Chris@16 1146 if (this != &v) {
Chris@16 1147 std::swap (size_, v.size_);
Chris@16 1148 std::swap (capacity_, v.capacity_);
Chris@16 1149 std::swap (filled_, v.filled_);
Chris@16 1150 index_data_.swap (v.index_data_);
Chris@16 1151 value_data_.swap (v.value_data_);
Chris@16 1152 }
Chris@16 1153 storage_invariants ();
Chris@16 1154 }
Chris@16 1155 BOOST_UBLAS_INLINE
Chris@16 1156 friend void swap (compressed_vector &v1, compressed_vector &v2) {
Chris@16 1157 v1.swap (v2);
Chris@16 1158 }
Chris@16 1159
Chris@16 1160 // Back element insertion and erasure
Chris@16 1161 BOOST_UBLAS_INLINE
Chris@16 1162 void push_back (size_type i, const_reference t) {
Chris@16 1163 BOOST_UBLAS_CHECK (filled_ == 0 || index_data_ [filled_ - 1] < k_based (i), external_logic ());
Chris@16 1164 if (filled_ >= capacity_)
Chris@16 1165 reserve (2 * capacity_, true);
Chris@16 1166 BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
Chris@16 1167 index_data_ [filled_] = k_based (i);
Chris@16 1168 value_data_ [filled_] = t;
Chris@16 1169 ++ filled_;
Chris@16 1170 storage_invariants ();
Chris@16 1171 }
Chris@16 1172 BOOST_UBLAS_INLINE
Chris@16 1173 void pop_back () {
Chris@16 1174 BOOST_UBLAS_CHECK (filled_ > 0, external_logic ());
Chris@16 1175 -- filled_;
Chris@16 1176 storage_invariants ();
Chris@16 1177 }
Chris@16 1178
Chris@16 1179 // Iterator types
Chris@16 1180 private:
Chris@16 1181 // Use index array iterator
Chris@16 1182 typedef typename IA::const_iterator const_subiterator_type;
Chris@16 1183 typedef typename IA::iterator subiterator_type;
Chris@16 1184
Chris@16 1185 BOOST_UBLAS_INLINE
Chris@16 1186 true_reference at_element (size_type i) {
Chris@16 1187 BOOST_UBLAS_CHECK (i < size_, bad_index ());
Chris@16 1188 subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 1189 BOOST_UBLAS_CHECK (it != index_data_.begin () + filled_ && *it == k_based (i), bad_index ());
Chris@16 1190 return value_data_ [it - index_data_.begin ()];
Chris@16 1191 }
Chris@16 1192
Chris@16 1193 public:
Chris@16 1194 class const_iterator;
Chris@16 1195 class iterator;
Chris@16 1196
Chris@16 1197 // Element lookup
Chris@16 1198 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 1199 const_iterator find (size_type i) const {
Chris@16 1200 return const_iterator (*this, detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 1201 }
Chris@16 1202 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 1203 iterator find (size_type i) {
Chris@16 1204 return iterator (*this, detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 1205 }
Chris@16 1206
Chris@16 1207
Chris@16 1208 class const_iterator:
Chris@16 1209 public container_const_reference<compressed_vector>,
Chris@16 1210 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 1211 const_iterator, value_type> {
Chris@16 1212 public:
Chris@16 1213 typedef typename compressed_vector::value_type value_type;
Chris@16 1214 typedef typename compressed_vector::difference_type difference_type;
Chris@16 1215 typedef typename compressed_vector::const_reference reference;
Chris@16 1216 typedef const typename compressed_vector::pointer pointer;
Chris@16 1217
Chris@16 1218 // Construction and destruction
Chris@16 1219 BOOST_UBLAS_INLINE
Chris@16 1220 const_iterator ():
Chris@16 1221 container_const_reference<self_type> (), it_ () {}
Chris@16 1222 BOOST_UBLAS_INLINE
Chris@16 1223 const_iterator (const self_type &v, const const_subiterator_type &it):
Chris@16 1224 container_const_reference<self_type> (v), it_ (it) {}
Chris@16 1225 BOOST_UBLAS_INLINE
Chris@16 1226 const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
Chris@16 1227 container_const_reference<self_type> (it ()), it_ (it.it_) {}
Chris@16 1228
Chris@16 1229 // Arithmetic
Chris@16 1230 BOOST_UBLAS_INLINE
Chris@16 1231 const_iterator &operator ++ () {
Chris@16 1232 ++ it_;
Chris@16 1233 return *this;
Chris@16 1234 }
Chris@16 1235 BOOST_UBLAS_INLINE
Chris@16 1236 const_iterator &operator -- () {
Chris@16 1237 -- it_;
Chris@16 1238 return *this;
Chris@16 1239 }
Chris@16 1240
Chris@16 1241 // Dereference
Chris@16 1242 BOOST_UBLAS_INLINE
Chris@16 1243 const_reference operator * () const {
Chris@16 1244 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
Chris@16 1245 return (*this) ().value_data_ [it_ - (*this) ().index_data_.begin ()];
Chris@16 1246 }
Chris@16 1247
Chris@16 1248 // Index
Chris@16 1249 BOOST_UBLAS_INLINE
Chris@16 1250 size_type index () const {
Chris@16 1251 BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
Chris@16 1252 BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
Chris@16 1253 return (*this) ().zero_based (*it_);
Chris@16 1254 }
Chris@16 1255
Chris@16 1256 // Assignment
Chris@16 1257 BOOST_UBLAS_INLINE
Chris@16 1258 const_iterator &operator = (const const_iterator &it) {
Chris@16 1259 container_const_reference<self_type>::assign (&it ());
Chris@16 1260 it_ = it.it_;
Chris@16 1261 return *this;
Chris@16 1262 }
Chris@16 1263
Chris@16 1264 // Comparison
Chris@16 1265 BOOST_UBLAS_INLINE
Chris@16 1266 bool operator == (const const_iterator &it) const {
Chris@16 1267 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 1268 return it_ == it.it_;
Chris@16 1269 }
Chris@16 1270
Chris@16 1271 private:
Chris@16 1272 const_subiterator_type it_;
Chris@16 1273 };
Chris@16 1274
Chris@16 1275 BOOST_UBLAS_INLINE
Chris@16 1276 const_iterator begin () const {
Chris@16 1277 return find (0);
Chris@16 1278 }
Chris@16 1279 BOOST_UBLAS_INLINE
Chris@101 1280 const_iterator cbegin () const {
Chris@101 1281 return begin ();
Chris@101 1282 }
Chris@101 1283 BOOST_UBLAS_INLINE
Chris@16 1284 const_iterator end () const {
Chris@16 1285 return find (size_);
Chris@16 1286 }
Chris@101 1287 BOOST_UBLAS_INLINE
Chris@101 1288 const_iterator cend () const {
Chris@101 1289 return end ();
Chris@101 1290 }
Chris@16 1291
Chris@16 1292 class iterator:
Chris@16 1293 public container_reference<compressed_vector>,
Chris@16 1294 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 1295 iterator, value_type> {
Chris@16 1296 public:
Chris@16 1297 typedef typename compressed_vector::value_type value_type;
Chris@16 1298 typedef typename compressed_vector::difference_type difference_type;
Chris@16 1299 typedef typename compressed_vector::true_reference reference;
Chris@16 1300 typedef typename compressed_vector::pointer pointer;
Chris@16 1301
Chris@16 1302 // Construction and destruction
Chris@16 1303 BOOST_UBLAS_INLINE
Chris@16 1304 iterator ():
Chris@16 1305 container_reference<self_type> (), it_ () {}
Chris@16 1306 BOOST_UBLAS_INLINE
Chris@16 1307 iterator (self_type &v, const subiterator_type &it):
Chris@16 1308 container_reference<self_type> (v), it_ (it) {}
Chris@16 1309
Chris@16 1310 // Arithmetic
Chris@16 1311 BOOST_UBLAS_INLINE
Chris@16 1312 iterator &operator ++ () {
Chris@16 1313 ++ it_;
Chris@16 1314 return *this;
Chris@16 1315 }
Chris@16 1316 BOOST_UBLAS_INLINE
Chris@16 1317 iterator &operator -- () {
Chris@16 1318 -- it_;
Chris@16 1319 return *this;
Chris@16 1320 }
Chris@16 1321
Chris@16 1322 // Dereference
Chris@16 1323 BOOST_UBLAS_INLINE
Chris@16 1324 reference operator * () const {
Chris@16 1325 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
Chris@16 1326 return (*this) ().value_data_ [it_ - (*this) ().index_data_.begin ()];
Chris@16 1327 }
Chris@16 1328
Chris@16 1329 // Index
Chris@16 1330 BOOST_UBLAS_INLINE
Chris@16 1331 size_type index () const {
Chris@16 1332 BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
Chris@16 1333 BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
Chris@16 1334 return (*this) ().zero_based (*it_);
Chris@16 1335 }
Chris@16 1336
Chris@16 1337 // Assignment
Chris@16 1338 BOOST_UBLAS_INLINE
Chris@16 1339 iterator &operator = (const iterator &it) {
Chris@16 1340 container_reference<self_type>::assign (&it ());
Chris@16 1341 it_ = it.it_;
Chris@16 1342 return *this;
Chris@16 1343 }
Chris@16 1344
Chris@16 1345 // Comparison
Chris@16 1346 BOOST_UBLAS_INLINE
Chris@16 1347 bool operator == (const iterator &it) const {
Chris@16 1348 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 1349 return it_ == it.it_;
Chris@16 1350 }
Chris@16 1351
Chris@16 1352 private:
Chris@16 1353 subiterator_type it_;
Chris@16 1354
Chris@16 1355 friend class const_iterator;
Chris@16 1356 };
Chris@16 1357
Chris@16 1358 BOOST_UBLAS_INLINE
Chris@16 1359 iterator begin () {
Chris@16 1360 return find (0);
Chris@16 1361 }
Chris@16 1362 BOOST_UBLAS_INLINE
Chris@16 1363 iterator end () {
Chris@16 1364 return find (size_);
Chris@16 1365 }
Chris@16 1366
Chris@16 1367 // Reverse iterator
Chris@16 1368 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
Chris@16 1369 typedef reverse_iterator_base<iterator> reverse_iterator;
Chris@16 1370
Chris@16 1371 BOOST_UBLAS_INLINE
Chris@16 1372 const_reverse_iterator rbegin () const {
Chris@16 1373 return const_reverse_iterator (end ());
Chris@16 1374 }
Chris@16 1375 BOOST_UBLAS_INLINE
Chris@101 1376 const_reverse_iterator crbegin () const {
Chris@101 1377 return rbegin ();
Chris@101 1378 }
Chris@101 1379 BOOST_UBLAS_INLINE
Chris@16 1380 const_reverse_iterator rend () const {
Chris@16 1381 return const_reverse_iterator (begin ());
Chris@16 1382 }
Chris@16 1383 BOOST_UBLAS_INLINE
Chris@101 1384 const_reverse_iterator crend () const {
Chris@101 1385 return rend ();
Chris@101 1386 }
Chris@101 1387 BOOST_UBLAS_INLINE
Chris@16 1388 reverse_iterator rbegin () {
Chris@16 1389 return reverse_iterator (end ());
Chris@16 1390 }
Chris@16 1391 BOOST_UBLAS_INLINE
Chris@16 1392 reverse_iterator rend () {
Chris@16 1393 return reverse_iterator (begin ());
Chris@16 1394 }
Chris@16 1395
Chris@16 1396 // Serialization
Chris@16 1397 template<class Archive>
Chris@16 1398 void serialize(Archive & ar, const unsigned int /* file_version */){
Chris@16 1399 serialization::collection_size_type s (size_);
Chris@16 1400 ar & serialization::make_nvp("size",s);
Chris@16 1401 if (Archive::is_loading::value) {
Chris@16 1402 size_ = s;
Chris@16 1403 }
Chris@16 1404 // ISSUE: filled may be much less than capacity
Chris@16 1405 // ISSUE: index_data_ and value_data_ are undefined between filled and capacity (trouble with 'nan'-values)
Chris@16 1406 ar & serialization::make_nvp("capacity", capacity_);
Chris@16 1407 ar & serialization::make_nvp("filled", filled_);
Chris@16 1408 ar & serialization::make_nvp("index_data", index_data_);
Chris@16 1409 ar & serialization::make_nvp("value_data", value_data_);
Chris@16 1410 storage_invariants();
Chris@16 1411 }
Chris@16 1412
Chris@16 1413 private:
Chris@16 1414 void storage_invariants () const
Chris@16 1415 {
Chris@16 1416 BOOST_UBLAS_CHECK (capacity_ == index_data_.size (), internal_logic ());
Chris@16 1417 BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
Chris@16 1418 BOOST_UBLAS_CHECK (filled_ <= capacity_, internal_logic ());
Chris@16 1419 BOOST_UBLAS_CHECK ((0 == filled_) || (zero_based(index_data_[filled_ - 1]) < size_), internal_logic ());
Chris@16 1420 }
Chris@16 1421
Chris@16 1422 size_type size_;
Chris@16 1423 typename index_array_type::size_type capacity_;
Chris@16 1424 typename index_array_type::size_type filled_;
Chris@16 1425 index_array_type index_data_;
Chris@16 1426 value_array_type value_data_;
Chris@16 1427 static const value_type zero_;
Chris@16 1428
Chris@16 1429 BOOST_UBLAS_INLINE
Chris@16 1430 static size_type zero_based (size_type k_based_index) {
Chris@16 1431 return k_based_index - IB;
Chris@16 1432 }
Chris@16 1433 BOOST_UBLAS_INLINE
Chris@16 1434 static size_type k_based (size_type zero_based_index) {
Chris@16 1435 return zero_based_index + IB;
Chris@16 1436 }
Chris@16 1437
Chris@16 1438 friend class iterator;
Chris@16 1439 friend class const_iterator;
Chris@16 1440 };
Chris@16 1441
Chris@16 1442 template<class T, std::size_t IB, class IA, class TA>
Chris@16 1443 const typename compressed_vector<T, IB, IA, TA>::value_type compressed_vector<T, IB, IA, TA>::zero_ = value_type/*zero*/();
Chris@16 1444
Chris@16 1445 // Thanks to Kresimir Fresl for extending this to cover different index bases.
Chris@16 1446
Chris@16 1447 /** \brief Coordimate array based sparse vector
Chris@16 1448 *
Chris@16 1449 * a sparse vector of values of type \c T of variable size. The non zero values are stored
Chris@16 1450 * as two seperate arrays: an index array and a value array. The arrays may be out of order
Chris@16 1451 * with multiple entries for each vector element. If there are multiple values for the same
Chris@16 1452 * index the sum of these values is the real value. It is way more efficient for inserting values
Chris@16 1453 * than a \c compressed_vector but less memory efficient. Also linearly parsing a vector can
Chris@16 1454 * be longer in specific cases than a \c compressed_vector.
Chris@16 1455 *
Chris@16 1456 * For a n-dimensional sorted coordinate vector and \f$ 0 \leq i < n\f$ the non-zero elements
Chris@16 1457 * \f$v_i\f$ are mapped to consecutive elements of the index and value container, i.e. for
Chris@16 1458 * elements \f$k = v_{i_1}\f$ and \f$k + 1 = v_{i_2}\f$ of these containers holds \f$i_1 < i_2\f$.
Chris@16 1459 *
Chris@16 1460 * Supported parameters for the adapted array (indices and values) are \c unbounded_array<> ,
Chris@16 1461 * \c bounded_array<> and \c std::vector<>.
Chris@16 1462 *
Chris@16 1463 * \tparam T the type of object stored in the vector (like double, float, complex, etc...)
Chris@16 1464 * \tparam IB the index base of the compressed vector. Default is 0. Other supported value is 1
Chris@16 1465 * \tparam IA the type of adapted array for indices. Default is \c unbounded_array<std::size_t>
Chris@16 1466 * \tparam TA the type of adapted array for values. Default is unbounded_array<T>
Chris@16 1467 */
Chris@16 1468 template<class T, std::size_t IB, class IA, class TA>
Chris@16 1469 class coordinate_vector:
Chris@16 1470 public vector_container<coordinate_vector<T, IB, IA, TA> > {
Chris@16 1471
Chris@16 1472 typedef T &true_reference;
Chris@16 1473 typedef T *pointer;
Chris@16 1474 typedef const T *const_pointer;
Chris@16 1475 typedef coordinate_vector<T, IB, IA, TA> self_type;
Chris@16 1476 public:
Chris@16 1477 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
Chris@16 1478 using vector_container<self_type>::operator ();
Chris@16 1479 #endif
Chris@16 1480 // ISSUE require type consistency check
Chris@16 1481 // is_convertable (IA::size_type, TA::size_type)
Chris@16 1482 typedef typename IA::value_type size_type;
Chris@16 1483 typedef typename IA::difference_type difference_type;
Chris@16 1484 typedef T value_type;
Chris@16 1485 typedef const T &const_reference;
Chris@16 1486 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
Chris@16 1487 typedef T &reference;
Chris@16 1488 #else
Chris@16 1489 typedef sparse_vector_element<self_type> reference;
Chris@16 1490 #endif
Chris@16 1491 typedef IA index_array_type;
Chris@16 1492 typedef TA value_array_type;
Chris@16 1493 typedef const vector_reference<const self_type> const_closure_type;
Chris@16 1494 typedef vector_reference<self_type> closure_type;
Chris@16 1495 typedef self_type vector_temporary_type;
Chris@16 1496 typedef sparse_tag storage_category;
Chris@16 1497
Chris@16 1498 // Construction and destruction
Chris@16 1499 BOOST_UBLAS_INLINE
Chris@16 1500 coordinate_vector ():
Chris@16 1501 vector_container<self_type> (),
Chris@16 1502 size_ (0), capacity_ (restrict_capacity (0)),
Chris@16 1503 filled_ (0), sorted_filled_ (filled_), sorted_ (true),
Chris@16 1504 index_data_ (capacity_), value_data_ (capacity_) {
Chris@16 1505 storage_invariants ();
Chris@16 1506 }
Chris@16 1507 explicit BOOST_UBLAS_INLINE
Chris@16 1508 coordinate_vector (size_type size, size_type non_zeros = 0):
Chris@16 1509 vector_container<self_type> (),
Chris@16 1510 size_ (size), capacity_ (restrict_capacity (non_zeros)),
Chris@16 1511 filled_ (0), sorted_filled_ (filled_), sorted_ (true),
Chris@16 1512 index_data_ (capacity_), value_data_ (capacity_) {
Chris@16 1513 storage_invariants ();
Chris@16 1514 }
Chris@16 1515 BOOST_UBLAS_INLINE
Chris@16 1516 coordinate_vector (const coordinate_vector &v):
Chris@16 1517 vector_container<self_type> (),
Chris@16 1518 size_ (v.size_), capacity_ (v.capacity_),
Chris@16 1519 filled_ (v.filled_), sorted_filled_ (v.sorted_filled_), sorted_ (v.sorted_),
Chris@16 1520 index_data_ (v.index_data_), value_data_ (v.value_data_) {
Chris@16 1521 storage_invariants ();
Chris@16 1522 }
Chris@16 1523 template<class AE>
Chris@16 1524 BOOST_UBLAS_INLINE
Chris@16 1525 coordinate_vector (const vector_expression<AE> &ae, size_type non_zeros = 0):
Chris@16 1526 vector_container<self_type> (),
Chris@16 1527 size_ (ae ().size ()), capacity_ (restrict_capacity (non_zeros)),
Chris@16 1528 filled_ (0), sorted_filled_ (filled_), sorted_ (true),
Chris@16 1529 index_data_ (capacity_), value_data_ (capacity_) {
Chris@16 1530 storage_invariants ();
Chris@16 1531 vector_assign<scalar_assign> (*this, ae);
Chris@16 1532 }
Chris@16 1533
Chris@16 1534 // Accessors
Chris@16 1535 BOOST_UBLAS_INLINE
Chris@16 1536 size_type size () const {
Chris@16 1537 return size_;
Chris@16 1538 }
Chris@16 1539 BOOST_UBLAS_INLINE
Chris@16 1540 size_type nnz_capacity () const {
Chris@16 1541 return capacity_;
Chris@16 1542 }
Chris@16 1543 BOOST_UBLAS_INLINE
Chris@16 1544 size_type nnz () const {
Chris@16 1545 return filled_;
Chris@16 1546 }
Chris@16 1547
Chris@16 1548 // Storage accessors
Chris@16 1549 BOOST_UBLAS_INLINE
Chris@16 1550 static size_type index_base () {
Chris@16 1551 return IB;
Chris@16 1552 }
Chris@16 1553 BOOST_UBLAS_INLINE
Chris@16 1554 typename index_array_type::size_type filled () const {
Chris@16 1555 return filled_;
Chris@16 1556 }
Chris@16 1557 BOOST_UBLAS_INLINE
Chris@16 1558 const index_array_type &index_data () const {
Chris@16 1559 return index_data_;
Chris@16 1560 }
Chris@16 1561 BOOST_UBLAS_INLINE
Chris@16 1562 const value_array_type &value_data () const {
Chris@16 1563 return value_data_;
Chris@16 1564 }
Chris@16 1565 BOOST_UBLAS_INLINE
Chris@16 1566 void set_filled (const typename index_array_type::size_type &sorted, const typename index_array_type::size_type &filled) {
Chris@16 1567 sorted_filled_ = sorted;
Chris@16 1568 filled_ = filled;
Chris@16 1569 storage_invariants ();
Chris@16 1570 }
Chris@16 1571 BOOST_UBLAS_INLINE
Chris@16 1572 index_array_type &index_data () {
Chris@16 1573 return index_data_;
Chris@16 1574 }
Chris@16 1575 BOOST_UBLAS_INLINE
Chris@16 1576 value_array_type &value_data () {
Chris@16 1577 return value_data_;
Chris@16 1578 }
Chris@16 1579
Chris@16 1580 // Resizing
Chris@16 1581 private:
Chris@16 1582 BOOST_UBLAS_INLINE
Chris@16 1583 size_type restrict_capacity (size_type non_zeros) const {
Chris@16 1584 // minimum non_zeros
Chris@16 1585 non_zeros = (std::max) (non_zeros, size_type (1));
Chris@16 1586 // ISSUE no maximum as coordinate may contain inserted duplicates
Chris@16 1587 return non_zeros;
Chris@16 1588 }
Chris@16 1589 public:
Chris@16 1590 BOOST_UBLAS_INLINE
Chris@16 1591 void resize (size_type size, bool preserve = true) {
Chris@16 1592 if (preserve)
Chris@16 1593 sort (); // remove duplicate elements.
Chris@16 1594 size_ = size;
Chris@16 1595 capacity_ = restrict_capacity (capacity_);
Chris@16 1596 if (preserve) {
Chris@16 1597 index_data_. resize (capacity_, size_type ());
Chris@16 1598 value_data_. resize (capacity_, value_type ());
Chris@16 1599 filled_ = (std::min) (capacity_, filled_);
Chris@16 1600 while ((filled_ > 0) && (zero_based(index_data_[filled_ - 1]) >= size)) {
Chris@16 1601 --filled_;
Chris@16 1602 }
Chris@16 1603 }
Chris@16 1604 else {
Chris@16 1605 index_data_. resize (capacity_);
Chris@16 1606 value_data_. resize (capacity_);
Chris@16 1607 filled_ = 0;
Chris@16 1608 }
Chris@16 1609 sorted_filled_ = filled_;
Chris@16 1610 storage_invariants ();
Chris@16 1611 }
Chris@16 1612 // Reserving
Chris@16 1613 BOOST_UBLAS_INLINE
Chris@16 1614 void reserve (size_type non_zeros, bool preserve = true) {
Chris@16 1615 if (preserve)
Chris@16 1616 sort (); // remove duplicate elements.
Chris@16 1617 capacity_ = restrict_capacity (non_zeros);
Chris@16 1618 if (preserve) {
Chris@16 1619 index_data_. resize (capacity_, size_type ());
Chris@16 1620 value_data_. resize (capacity_, value_type ());
Chris@16 1621 filled_ = (std::min) (capacity_, filled_);
Chris@16 1622 }
Chris@16 1623 else {
Chris@16 1624 index_data_. resize (capacity_);
Chris@16 1625 value_data_. resize (capacity_);
Chris@16 1626 filled_ = 0;
Chris@16 1627 }
Chris@16 1628 sorted_filled_ = filled_;
Chris@16 1629 storage_invariants ();
Chris@16 1630 }
Chris@16 1631
Chris@16 1632 // Element support
Chris@16 1633 BOOST_UBLAS_INLINE
Chris@16 1634 pointer find_element (size_type i) {
Chris@16 1635 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
Chris@16 1636 }
Chris@16 1637 BOOST_UBLAS_INLINE
Chris@16 1638 const_pointer find_element (size_type i) const {
Chris@16 1639 sort ();
Chris@16 1640 const_subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 1641 if (it == index_data_.begin () + filled_ || *it != k_based (i))
Chris@16 1642 return 0;
Chris@16 1643 return &value_data_ [it - index_data_.begin ()];
Chris@16 1644 }
Chris@16 1645
Chris@16 1646 // Element access
Chris@16 1647 BOOST_UBLAS_INLINE
Chris@16 1648 const_reference operator () (size_type i) const {
Chris@16 1649 BOOST_UBLAS_CHECK (i < size_, bad_index ());
Chris@16 1650 sort ();
Chris@16 1651 const_subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 1652 if (it == index_data_.begin () + filled_ || *it != k_based (i))
Chris@16 1653 return zero_;
Chris@16 1654 return value_data_ [it - index_data_.begin ()];
Chris@16 1655 }
Chris@16 1656 BOOST_UBLAS_INLINE
Chris@16 1657 true_reference ref (size_type i) {
Chris@16 1658 BOOST_UBLAS_CHECK (i < size_, bad_index ());
Chris@16 1659 sort ();
Chris@16 1660 subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 1661 if (it == index_data_.begin () + filled_ || *it != k_based (i))
Chris@16 1662 return insert_element (i, value_type/*zero*/());
Chris@16 1663 else
Chris@16 1664 return value_data_ [it - index_data_.begin ()];
Chris@16 1665 }
Chris@16 1666 BOOST_UBLAS_INLINE
Chris@16 1667 reference operator () (size_type i) {
Chris@16 1668 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
Chris@16 1669 return ref (i);
Chris@16 1670 #else
Chris@16 1671 BOOST_UBLAS_CHECK (i < size_, bad_index ());
Chris@16 1672 return reference (*this, i);
Chris@16 1673 #endif
Chris@16 1674 }
Chris@16 1675
Chris@16 1676 BOOST_UBLAS_INLINE
Chris@16 1677 const_reference operator [] (size_type i) const {
Chris@16 1678 return (*this) (i);
Chris@16 1679 }
Chris@16 1680 BOOST_UBLAS_INLINE
Chris@16 1681 reference operator [] (size_type i) {
Chris@16 1682 return (*this) (i);
Chris@16 1683 }
Chris@16 1684
Chris@16 1685 // Element assignment
Chris@16 1686 BOOST_UBLAS_INLINE
Chris@16 1687 void append_element (size_type i, const_reference t) {
Chris@16 1688 if (filled_ >= capacity_)
Chris@16 1689 reserve (2 * filled_, true);
Chris@16 1690 BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
Chris@16 1691 index_data_ [filled_] = k_based (i);
Chris@16 1692 value_data_ [filled_] = t;
Chris@16 1693 ++ filled_;
Chris@16 1694 sorted_ = false;
Chris@16 1695 storage_invariants ();
Chris@16 1696 }
Chris@16 1697 BOOST_UBLAS_INLINE
Chris@16 1698 true_reference insert_element (size_type i, const_reference t) {
Chris@16 1699 BOOST_UBLAS_CHECK (!find_element (i), bad_index ()); // duplicate element
Chris@16 1700 append_element (i, t);
Chris@16 1701 return value_data_ [filled_ - 1];
Chris@16 1702 }
Chris@16 1703 BOOST_UBLAS_INLINE
Chris@16 1704 void erase_element (size_type i) {
Chris@16 1705 sort ();
Chris@16 1706 subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 1707 typename std::iterator_traits<subiterator_type>::difference_type n = it - index_data_.begin ();
Chris@16 1708 if (filled_ > typename index_array_type::size_type (n) && *it == k_based (i)) {
Chris@16 1709 std::copy (it + 1, index_data_.begin () + filled_, it);
Chris@16 1710 typename value_array_type::iterator itt (value_data_.begin () + n);
Chris@16 1711 std::copy (itt + 1, value_data_.begin () + filled_, itt);
Chris@16 1712 -- filled_;
Chris@16 1713 sorted_filled_ = filled_;
Chris@16 1714 }
Chris@16 1715 storage_invariants ();
Chris@16 1716 }
Chris@16 1717
Chris@16 1718 // Zeroing
Chris@16 1719 BOOST_UBLAS_INLINE
Chris@16 1720 void clear () {
Chris@16 1721 filled_ = 0;
Chris@16 1722 sorted_filled_ = filled_;
Chris@16 1723 sorted_ = true;
Chris@16 1724 storage_invariants ();
Chris@16 1725 }
Chris@16 1726
Chris@16 1727 // Assignment
Chris@16 1728 BOOST_UBLAS_INLINE
Chris@16 1729 coordinate_vector &operator = (const coordinate_vector &v) {
Chris@16 1730 if (this != &v) {
Chris@16 1731 size_ = v.size_;
Chris@16 1732 capacity_ = v.capacity_;
Chris@16 1733 filled_ = v.filled_;
Chris@16 1734 sorted_filled_ = v.sorted_filled_;
Chris@16 1735 sorted_ = v.sorted_;
Chris@16 1736 index_data_ = v.index_data_;
Chris@16 1737 value_data_ = v.value_data_;
Chris@16 1738 }
Chris@16 1739 storage_invariants ();
Chris@16 1740 return *this;
Chris@16 1741 }
Chris@16 1742 template<class C> // Container assignment without temporary
Chris@16 1743 BOOST_UBLAS_INLINE
Chris@16 1744 coordinate_vector &operator = (const vector_container<C> &v) {
Chris@16 1745 resize (v ().size (), false);
Chris@16 1746 assign (v);
Chris@16 1747 return *this;
Chris@16 1748 }
Chris@16 1749 BOOST_UBLAS_INLINE
Chris@16 1750 coordinate_vector &assign_temporary (coordinate_vector &v) {
Chris@16 1751 swap (v);
Chris@16 1752 return *this;
Chris@16 1753 }
Chris@16 1754 template<class AE>
Chris@16 1755 BOOST_UBLAS_INLINE
Chris@16 1756 coordinate_vector &operator = (const vector_expression<AE> &ae) {
Chris@16 1757 self_type temporary (ae, capacity_);
Chris@16 1758 return assign_temporary (temporary);
Chris@16 1759 }
Chris@16 1760 template<class AE>
Chris@16 1761 BOOST_UBLAS_INLINE
Chris@16 1762 coordinate_vector &assign (const vector_expression<AE> &ae) {
Chris@16 1763 vector_assign<scalar_assign> (*this, ae);
Chris@16 1764 return *this;
Chris@16 1765 }
Chris@16 1766
Chris@16 1767 // Computed assignment
Chris@16 1768 template<class AE>
Chris@16 1769 BOOST_UBLAS_INLINE
Chris@16 1770 coordinate_vector &operator += (const vector_expression<AE> &ae) {
Chris@16 1771 self_type temporary (*this + ae, capacity_);
Chris@16 1772 return assign_temporary (temporary);
Chris@16 1773 }
Chris@16 1774 template<class C> // Container assignment without temporary
Chris@16 1775 BOOST_UBLAS_INLINE
Chris@16 1776 coordinate_vector &operator += (const vector_container<C> &v) {
Chris@16 1777 plus_assign (v);
Chris@16 1778 return *this;
Chris@16 1779 }
Chris@16 1780 template<class AE>
Chris@16 1781 BOOST_UBLAS_INLINE
Chris@16 1782 coordinate_vector &plus_assign (const vector_expression<AE> &ae) {
Chris@16 1783 vector_assign<scalar_plus_assign> (*this, ae);
Chris@16 1784 return *this;
Chris@16 1785 }
Chris@16 1786 template<class AE>
Chris@16 1787 BOOST_UBLAS_INLINE
Chris@16 1788 coordinate_vector &operator -= (const vector_expression<AE> &ae) {
Chris@16 1789 self_type temporary (*this - ae, capacity_);
Chris@16 1790 return assign_temporary (temporary);
Chris@16 1791 }
Chris@16 1792 template<class C> // Container assignment without temporary
Chris@16 1793 BOOST_UBLAS_INLINE
Chris@16 1794 coordinate_vector &operator -= (const vector_container<C> &v) {
Chris@16 1795 minus_assign (v);
Chris@16 1796 return *this;
Chris@16 1797 }
Chris@16 1798 template<class AE>
Chris@16 1799 BOOST_UBLAS_INLINE
Chris@16 1800 coordinate_vector &minus_assign (const vector_expression<AE> &ae) {
Chris@16 1801 vector_assign<scalar_minus_assign> (*this, ae);
Chris@16 1802 return *this;
Chris@16 1803 }
Chris@16 1804 template<class AT>
Chris@16 1805 BOOST_UBLAS_INLINE
Chris@16 1806 coordinate_vector &operator *= (const AT &at) {
Chris@16 1807 vector_assign_scalar<scalar_multiplies_assign> (*this, at);
Chris@16 1808 return *this;
Chris@16 1809 }
Chris@16 1810 template<class AT>
Chris@16 1811 BOOST_UBLAS_INLINE
Chris@16 1812 coordinate_vector &operator /= (const AT &at) {
Chris@16 1813 vector_assign_scalar<scalar_divides_assign> (*this, at);
Chris@16 1814 return *this;
Chris@16 1815 }
Chris@16 1816
Chris@16 1817 // Swapping
Chris@16 1818 BOOST_UBLAS_INLINE
Chris@16 1819 void swap (coordinate_vector &v) {
Chris@16 1820 if (this != &v) {
Chris@16 1821 std::swap (size_, v.size_);
Chris@16 1822 std::swap (capacity_, v.capacity_);
Chris@16 1823 std::swap (filled_, v.filled_);
Chris@16 1824 std::swap (sorted_filled_, v.sorted_filled_);
Chris@16 1825 std::swap (sorted_, v.sorted_);
Chris@16 1826 index_data_.swap (v.index_data_);
Chris@16 1827 value_data_.swap (v.value_data_);
Chris@16 1828 }
Chris@16 1829 storage_invariants ();
Chris@16 1830 }
Chris@16 1831 BOOST_UBLAS_INLINE
Chris@16 1832 friend void swap (coordinate_vector &v1, coordinate_vector &v2) {
Chris@16 1833 v1.swap (v2);
Chris@16 1834 }
Chris@16 1835
Chris@16 1836 // replacement if STL lower bound algorithm for use of inplace_merge
Chris@16 1837 size_type lower_bound (size_type beg, size_type end, size_type target) const {
Chris@16 1838 while (end > beg) {
Chris@16 1839 size_type mid = (beg + end) / 2;
Chris@16 1840 if (index_data_[mid] < index_data_[target]) {
Chris@16 1841 beg = mid + 1;
Chris@16 1842 } else {
Chris@16 1843 end = mid;
Chris@16 1844 }
Chris@16 1845 }
Chris@16 1846 return beg;
Chris@16 1847 }
Chris@16 1848
Chris@16 1849 // specialized replacement of STL inplace_merge to avoid compilation
Chris@16 1850 // problems with respect to the array_triple iterator
Chris@16 1851 void inplace_merge (size_type beg, size_type mid, size_type end) const {
Chris@16 1852 size_type len_lef = mid - beg;
Chris@16 1853 size_type len_rig = end - mid;
Chris@16 1854
Chris@16 1855 if (len_lef == 1 && len_rig == 1) {
Chris@16 1856 if (index_data_[mid] < index_data_[beg]) {
Chris@16 1857 std::swap(index_data_[beg], index_data_[mid]);
Chris@16 1858 std::swap(value_data_[beg], value_data_[mid]);
Chris@16 1859 }
Chris@16 1860 } else if (len_lef > 0 && len_rig > 0) {
Chris@16 1861 size_type lef_mid, rig_mid;
Chris@16 1862 if (len_lef >= len_rig) {
Chris@16 1863 lef_mid = (beg + mid) / 2;
Chris@16 1864 rig_mid = lower_bound(mid, end, lef_mid);
Chris@16 1865 } else {
Chris@16 1866 rig_mid = (mid + end) / 2;
Chris@16 1867 lef_mid = lower_bound(beg, mid, rig_mid);
Chris@16 1868 }
Chris@16 1869 std::rotate(&index_data_[0] + lef_mid, &index_data_[0] + mid, &index_data_[0] + rig_mid);
Chris@16 1870 std::rotate(&value_data_[0] + lef_mid, &value_data_[0] + mid, &value_data_[0] + rig_mid);
Chris@16 1871
Chris@16 1872 size_type new_mid = lef_mid + rig_mid - mid;
Chris@16 1873 inplace_merge(beg, lef_mid, new_mid);
Chris@16 1874 inplace_merge(new_mid, rig_mid, end);
Chris@16 1875 }
Chris@16 1876 }
Chris@16 1877
Chris@16 1878 // Sorting and summation of duplicates
Chris@16 1879 BOOST_UBLAS_INLINE
Chris@16 1880 void sort () const {
Chris@16 1881 if (! sorted_ && filled_ > 0) {
Chris@16 1882 typedef index_pair_array<index_array_type, value_array_type> array_pair;
Chris@16 1883 array_pair ipa (filled_, index_data_, value_data_);
Chris@16 1884 #ifndef BOOST_UBLAS_COO_ALWAYS_DO_FULL_SORT
Chris@16 1885 const typename array_pair::iterator iunsorted = ipa.begin () + sorted_filled_;
Chris@16 1886 // sort new elements and merge
Chris@16 1887 std::sort (iunsorted, ipa.end ());
Chris@16 1888 inplace_merge(0, sorted_filled_, filled_);
Chris@16 1889 #else
Chris@16 1890 const typename array_pair::iterator iunsorted = ipa.begin ();
Chris@16 1891 std::sort (iunsorted, ipa.end ());
Chris@16 1892 #endif
Chris@16 1893
Chris@16 1894 // sum duplicates with += and remove
Chris@16 1895 size_type filled = 0;
Chris@16 1896 for (size_type i = 1; i < filled_; ++ i) {
Chris@16 1897 if (index_data_ [filled] != index_data_ [i]) {
Chris@16 1898 ++ filled;
Chris@16 1899 if (filled != i) {
Chris@16 1900 index_data_ [filled] = index_data_ [i];
Chris@16 1901 value_data_ [filled] = value_data_ [i];
Chris@16 1902 }
Chris@16 1903 } else {
Chris@16 1904 value_data_ [filled] += value_data_ [i];
Chris@16 1905 }
Chris@16 1906 }
Chris@16 1907 filled_ = filled + 1;
Chris@16 1908 sorted_filled_ = filled_;
Chris@16 1909 sorted_ = true;
Chris@16 1910 storage_invariants ();
Chris@16 1911 }
Chris@16 1912 }
Chris@16 1913
Chris@16 1914 // Back element insertion and erasure
Chris@16 1915 BOOST_UBLAS_INLINE
Chris@16 1916 void push_back (size_type i, const_reference t) {
Chris@16 1917 // must maintain sort order
Chris@16 1918 BOOST_UBLAS_CHECK (sorted_ && (filled_ == 0 || index_data_ [filled_ - 1] < k_based (i)), external_logic ());
Chris@16 1919 if (filled_ >= capacity_)
Chris@16 1920 reserve (2 * filled_, true);
Chris@16 1921 BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
Chris@16 1922 index_data_ [filled_] = k_based (i);
Chris@16 1923 value_data_ [filled_] = t;
Chris@16 1924 ++ filled_;
Chris@16 1925 sorted_filled_ = filled_;
Chris@16 1926 storage_invariants ();
Chris@16 1927 }
Chris@16 1928 BOOST_UBLAS_INLINE
Chris@16 1929 void pop_back () {
Chris@16 1930 // ISSUE invariants could be simpilfied if sorted required as precondition
Chris@16 1931 BOOST_UBLAS_CHECK (filled_ > 0, external_logic ());
Chris@16 1932 -- filled_;
Chris@16 1933 sorted_filled_ = (std::min) (sorted_filled_, filled_);
Chris@16 1934 sorted_ = sorted_filled_ = filled_;
Chris@16 1935 storage_invariants ();
Chris@16 1936 }
Chris@16 1937
Chris@16 1938 // Iterator types
Chris@16 1939 private:
Chris@16 1940 // Use index array iterator
Chris@16 1941 typedef typename IA::const_iterator const_subiterator_type;
Chris@16 1942 typedef typename IA::iterator subiterator_type;
Chris@16 1943
Chris@16 1944 BOOST_UBLAS_INLINE
Chris@16 1945 true_reference at_element (size_type i) {
Chris@16 1946 BOOST_UBLAS_CHECK (i < size_, bad_index ());
Chris@16 1947 sort ();
Chris@16 1948 subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 1949 BOOST_UBLAS_CHECK (it != index_data_.begin () + filled_ && *it == k_based (i), bad_index ());
Chris@16 1950 return value_data_ [it - index_data_.begin ()];
Chris@16 1951 }
Chris@16 1952
Chris@16 1953 public:
Chris@16 1954 class const_iterator;
Chris@16 1955 class iterator;
Chris@16 1956
Chris@16 1957 // Element lookup
Chris@16 1958 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 1959 const_iterator find (size_type i) const {
Chris@16 1960 sort ();
Chris@16 1961 return const_iterator (*this, detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 1962 }
Chris@16 1963 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
Chris@16 1964 iterator find (size_type i) {
Chris@16 1965 sort ();
Chris@16 1966 return iterator (*this, detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
Chris@16 1967 }
Chris@16 1968
Chris@16 1969
Chris@16 1970 class const_iterator:
Chris@16 1971 public container_const_reference<coordinate_vector>,
Chris@16 1972 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 1973 const_iterator, value_type> {
Chris@16 1974 public:
Chris@16 1975 typedef typename coordinate_vector::value_type value_type;
Chris@16 1976 typedef typename coordinate_vector::difference_type difference_type;
Chris@16 1977 typedef typename coordinate_vector::const_reference reference;
Chris@16 1978 typedef const typename coordinate_vector::pointer pointer;
Chris@16 1979
Chris@16 1980 // Construction and destruction
Chris@16 1981 BOOST_UBLAS_INLINE
Chris@16 1982 const_iterator ():
Chris@16 1983 container_const_reference<self_type> (), it_ () {}
Chris@16 1984 BOOST_UBLAS_INLINE
Chris@16 1985 const_iterator (const self_type &v, const const_subiterator_type &it):
Chris@16 1986 container_const_reference<self_type> (v), it_ (it) {}
Chris@16 1987 BOOST_UBLAS_INLINE
Chris@16 1988 const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
Chris@16 1989 container_const_reference<self_type> (it ()), it_ (it.it_) {}
Chris@16 1990
Chris@16 1991 // Arithmetic
Chris@16 1992 BOOST_UBLAS_INLINE
Chris@16 1993 const_iterator &operator ++ () {
Chris@16 1994 ++ it_;
Chris@16 1995 return *this;
Chris@16 1996 }
Chris@16 1997 BOOST_UBLAS_INLINE
Chris@16 1998 const_iterator &operator -- () {
Chris@16 1999 -- it_;
Chris@16 2000 return *this;
Chris@16 2001 }
Chris@16 2002
Chris@16 2003 // Dereference
Chris@16 2004 BOOST_UBLAS_INLINE
Chris@16 2005 const_reference operator * () const {
Chris@16 2006 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
Chris@16 2007 return (*this) ().value_data_ [it_ - (*this) ().index_data_.begin ()];
Chris@16 2008 }
Chris@16 2009
Chris@16 2010 // Index
Chris@16 2011 BOOST_UBLAS_INLINE
Chris@16 2012 size_type index () const {
Chris@16 2013 BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
Chris@16 2014 BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
Chris@16 2015 return (*this) ().zero_based (*it_);
Chris@16 2016 }
Chris@16 2017
Chris@16 2018 // Assignment
Chris@16 2019 BOOST_UBLAS_INLINE
Chris@16 2020 const_iterator &operator = (const const_iterator &it) {
Chris@16 2021 container_const_reference<self_type>::assign (&it ());
Chris@16 2022 it_ = it.it_;
Chris@16 2023 return *this;
Chris@16 2024 }
Chris@16 2025
Chris@16 2026 // Comparison
Chris@16 2027 BOOST_UBLAS_INLINE
Chris@16 2028 bool operator == (const const_iterator &it) const {
Chris@16 2029 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 2030 return it_ == it.it_;
Chris@16 2031 }
Chris@16 2032
Chris@16 2033 private:
Chris@16 2034 const_subiterator_type it_;
Chris@16 2035 };
Chris@16 2036
Chris@16 2037 BOOST_UBLAS_INLINE
Chris@16 2038 const_iterator begin () const {
Chris@16 2039 return find (0);
Chris@16 2040 }
Chris@16 2041 BOOST_UBLAS_INLINE
Chris@101 2042 const_iterator cbegin () const {
Chris@101 2043 return begin();
Chris@101 2044 }
Chris@101 2045 BOOST_UBLAS_INLINE
Chris@16 2046 const_iterator end () const {
Chris@16 2047 return find (size_);
Chris@16 2048 }
Chris@101 2049 BOOST_UBLAS_INLINE
Chris@101 2050 const_iterator cend () const {
Chris@101 2051 return end();
Chris@101 2052 }
Chris@16 2053
Chris@16 2054 class iterator:
Chris@16 2055 public container_reference<coordinate_vector>,
Chris@16 2056 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
Chris@16 2057 iterator, value_type> {
Chris@16 2058 public:
Chris@16 2059 typedef typename coordinate_vector::value_type value_type;
Chris@16 2060 typedef typename coordinate_vector::difference_type difference_type;
Chris@16 2061 typedef typename coordinate_vector::true_reference reference;
Chris@16 2062 typedef typename coordinate_vector::pointer pointer;
Chris@16 2063
Chris@16 2064 // Construction and destruction
Chris@16 2065 BOOST_UBLAS_INLINE
Chris@16 2066 iterator ():
Chris@16 2067 container_reference<self_type> (), it_ () {}
Chris@16 2068 BOOST_UBLAS_INLINE
Chris@16 2069 iterator (self_type &v, const subiterator_type &it):
Chris@16 2070 container_reference<self_type> (v), it_ (it) {}
Chris@16 2071
Chris@16 2072 // Arithmetic
Chris@16 2073 BOOST_UBLAS_INLINE
Chris@16 2074 iterator &operator ++ () {
Chris@16 2075 ++ it_;
Chris@16 2076 return *this;
Chris@16 2077 }
Chris@16 2078 BOOST_UBLAS_INLINE
Chris@16 2079 iterator &operator -- () {
Chris@16 2080 -- it_;
Chris@16 2081 return *this;
Chris@16 2082 }
Chris@16 2083
Chris@16 2084 // Dereference
Chris@16 2085 BOOST_UBLAS_INLINE
Chris@16 2086 reference operator * () const {
Chris@16 2087 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
Chris@16 2088 return (*this) ().value_data_ [it_ - (*this) ().index_data_.begin ()];
Chris@16 2089 }
Chris@16 2090
Chris@16 2091 // Index
Chris@16 2092 BOOST_UBLAS_INLINE
Chris@16 2093 size_type index () const {
Chris@16 2094 BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
Chris@16 2095 BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
Chris@16 2096 return (*this) ().zero_based (*it_);
Chris@16 2097 }
Chris@16 2098
Chris@16 2099 // Assignment
Chris@16 2100 BOOST_UBLAS_INLINE
Chris@16 2101 iterator &operator = (const iterator &it) {
Chris@16 2102 container_reference<self_type>::assign (&it ());
Chris@16 2103 it_ = it.it_;
Chris@16 2104 return *this;
Chris@16 2105 }
Chris@16 2106
Chris@16 2107 // Comparison
Chris@16 2108 BOOST_UBLAS_INLINE
Chris@16 2109 bool operator == (const iterator &it) const {
Chris@16 2110 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
Chris@16 2111 return it_ == it.it_;
Chris@16 2112 }
Chris@16 2113
Chris@16 2114 private:
Chris@16 2115 subiterator_type it_;
Chris@16 2116
Chris@16 2117 friend class const_iterator;
Chris@16 2118 };
Chris@16 2119
Chris@16 2120 BOOST_UBLAS_INLINE
Chris@16 2121 iterator begin () {
Chris@16 2122 return find (0);
Chris@16 2123 }
Chris@16 2124 BOOST_UBLAS_INLINE
Chris@16 2125 iterator end () {
Chris@16 2126 return find (size_);
Chris@16 2127 }
Chris@16 2128
Chris@16 2129 // Reverse iterator
Chris@16 2130 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
Chris@16 2131 typedef reverse_iterator_base<iterator> reverse_iterator;
Chris@16 2132
Chris@16 2133 BOOST_UBLAS_INLINE
Chris@16 2134 const_reverse_iterator rbegin () const {
Chris@16 2135 return const_reverse_iterator (end ());
Chris@16 2136 }
Chris@16 2137 BOOST_UBLAS_INLINE
Chris@101 2138 const_reverse_iterator crbegin () const {
Chris@101 2139 return rbegin ();
Chris@101 2140 }
Chris@101 2141 BOOST_UBLAS_INLINE
Chris@16 2142 const_reverse_iterator rend () const {
Chris@16 2143 return const_reverse_iterator (begin ());
Chris@16 2144 }
Chris@16 2145 BOOST_UBLAS_INLINE
Chris@101 2146 const_reverse_iterator crend () const {
Chris@101 2147 return rend ();
Chris@101 2148 }
Chris@101 2149 BOOST_UBLAS_INLINE
Chris@16 2150 reverse_iterator rbegin () {
Chris@16 2151 return reverse_iterator (end ());
Chris@16 2152 }
Chris@16 2153 BOOST_UBLAS_INLINE
Chris@16 2154 reverse_iterator rend () {
Chris@16 2155 return reverse_iterator (begin ());
Chris@16 2156 }
Chris@16 2157
Chris@16 2158 // Serialization
Chris@16 2159 template<class Archive>
Chris@16 2160 void serialize(Archive & ar, const unsigned int /* file_version */){
Chris@16 2161 serialization::collection_size_type s (size_);
Chris@16 2162 ar & serialization::make_nvp("size",s);
Chris@16 2163 if (Archive::is_loading::value) {
Chris@16 2164 size_ = s;
Chris@16 2165 }
Chris@16 2166 // ISSUE: filled may be much less than capacity
Chris@16 2167 // ISSUE: index_data_ and value_data_ are undefined between filled and capacity (trouble with 'nan'-values)
Chris@16 2168 ar & serialization::make_nvp("capacity", capacity_);
Chris@16 2169 ar & serialization::make_nvp("filled", filled_);
Chris@16 2170 ar & serialization::make_nvp("sorted_filled", sorted_filled_);
Chris@16 2171 ar & serialization::make_nvp("sorted", sorted_);
Chris@16 2172 ar & serialization::make_nvp("index_data", index_data_);
Chris@16 2173 ar & serialization::make_nvp("value_data", value_data_);
Chris@16 2174 storage_invariants();
Chris@16 2175 }
Chris@16 2176
Chris@16 2177 private:
Chris@16 2178 void storage_invariants () const
Chris@16 2179 {
Chris@16 2180 BOOST_UBLAS_CHECK (capacity_ == index_data_.size (), internal_logic ());
Chris@16 2181 BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
Chris@16 2182 BOOST_UBLAS_CHECK (filled_ <= capacity_, internal_logic ());
Chris@16 2183 BOOST_UBLAS_CHECK (sorted_filled_ <= filled_, internal_logic ());
Chris@16 2184 BOOST_UBLAS_CHECK (sorted_ == (sorted_filled_ == filled_), internal_logic ());
Chris@16 2185 BOOST_UBLAS_CHECK ((0 == filled_) || (zero_based(index_data_[filled_ - 1]) < size_), internal_logic ());
Chris@16 2186 }
Chris@16 2187
Chris@16 2188 size_type size_;
Chris@16 2189 size_type capacity_;
Chris@16 2190 mutable typename index_array_type::size_type filled_;
Chris@16 2191 mutable typename index_array_type::size_type sorted_filled_;
Chris@16 2192 mutable bool sorted_;
Chris@16 2193 mutable index_array_type index_data_;
Chris@16 2194 mutable value_array_type value_data_;
Chris@16 2195 static const value_type zero_;
Chris@16 2196
Chris@16 2197 BOOST_UBLAS_INLINE
Chris@16 2198 static size_type zero_based (size_type k_based_index) {
Chris@16 2199 return k_based_index - IB;
Chris@16 2200 }
Chris@16 2201 BOOST_UBLAS_INLINE
Chris@16 2202 static size_type k_based (size_type zero_based_index) {
Chris@16 2203 return zero_based_index + IB;
Chris@16 2204 }
Chris@16 2205
Chris@16 2206 friend class iterator;
Chris@16 2207 friend class const_iterator;
Chris@16 2208 };
Chris@16 2209
Chris@16 2210 template<class T, std::size_t IB, class IA, class TA>
Chris@16 2211 const typename coordinate_vector<T, IB, IA, TA>::value_type coordinate_vector<T, IB, IA, TA>::zero_ = value_type/*zero*/();
Chris@16 2212
Chris@16 2213 }}}
Chris@16 2214
Chris@16 2215 #endif