1 // 2 // Copyright (c) 2000-2002 3 // Joerg Walter, Mathias Koch 4 // 5 // Distributed under the Boost Software License, Version 1.0. (See 6 // accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 // 9 // The authors gratefully acknowledge the support of 10 // GeNeSys mbH & Co. KG in producing this work. 11 // 12 13 #ifndef BOOST_UBLAS_STORAGE_H 14 #define BOOST_UBLAS_STORAGE_H 15 16 #include <algorithm> 17 #ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR 18 #include <boost/shared_array.hpp> 19 #endif 20 21 #include <boost/serialization/array.hpp> 22 #include <boost/serialization/collection_size_type.hpp> 23 #include <boost/serialization/nvp.hpp> 24 25 #include <boost/numeric/ublas/exception.hpp> 26 #include <boost/numeric/ublas/traits.hpp> 27 #include <boost/numeric/ublas/detail/iterator.hpp> 28 29 30 namespace boost { namespace numeric { namespace ublas { 31 32 33 // Base class for Storage Arrays - see the Barton Nackman trick 34 template<class E> 35 class storage_array: 36 private nonassignable { 37 }; 38 39 40 // Unbounded array - with allocator 41 template<class T, class ALLOC> 42 class unbounded_array: 43 public storage_array<unbounded_array<T, ALLOC> > { 44 45 typedef unbounded_array<T, ALLOC> self_type; 46 public: 47 typedef ALLOC allocator_type; 48 typedef typename ALLOC::size_type size_type; 49 typedef typename ALLOC::difference_type difference_type; 50 typedef T value_type; 51 typedef const T &const_reference; 52 typedef T &reference; 53 typedef const T *const_pointer; 54 typedef T *pointer; 55 typedef const_pointer const_iterator; 56 typedef pointer iterator; 57 58 // Construction and destruction 59 explicit BOOST_UBLAS_INLINE unbounded_array(const ALLOC & a=ALLOC ())60 unbounded_array (const ALLOC &a = ALLOC()): 61 alloc_ (a), size_ (0) { 62 data_ = 0; 63 } 64 explicit BOOST_UBLAS_INLINE unbounded_array(size_type size,const ALLOC & a=ALLOC ())65 unbounded_array (size_type size, const ALLOC &a = ALLOC()): 66 alloc_(a), size_ (size) { 67 if (size_) { 68 data_ = alloc_.allocate (size_); 69 if (! detail::has_trivial_constructor<T>::value) { 70 for (pointer d = data_; d != data_ + size_; ++d) 71 alloc_.construct(d, value_type()); 72 } 73 } 74 else 75 data_ = 0; 76 } 77 // No value initialised, but still be default constructed 78 BOOST_UBLAS_INLINE unbounded_array(size_type size,const value_type & init,const ALLOC & a=ALLOC ())79 unbounded_array (size_type size, const value_type &init, const ALLOC &a = ALLOC()): 80 alloc_ (a), size_ (size) { 81 if (size_) { 82 data_ = alloc_.allocate (size_); 83 std::uninitialized_fill (begin(), end(), init); 84 } 85 else 86 data_ = 0; 87 } 88 BOOST_UBLAS_INLINE unbounded_array(const unbounded_array & c)89 unbounded_array (const unbounded_array &c): 90 storage_array<unbounded_array<T, ALLOC> >(), 91 alloc_ (c.alloc_), size_ (c.size_) { 92 if (size_) { 93 data_ = alloc_.allocate (size_); 94 std::uninitialized_copy (c.begin(), c.end(), begin()); 95 } 96 else 97 data_ = 0; 98 } 99 BOOST_UBLAS_INLINE ~unbounded_array()100 ~unbounded_array () { 101 if (size_) { 102 if (! detail::has_trivial_destructor<T>::value) { 103 // std::_Destroy (begin(), end(), alloc_); 104 const iterator i_end = end(); 105 for (iterator i = begin (); i != i_end; ++i) { 106 iterator_destroy (i); 107 } 108 } 109 alloc_.deallocate (data_, size_); 110 } 111 } 112 113 // Resizing 114 private: 115 BOOST_UBLAS_INLINE resize_internal(const size_type size,const value_type init,const bool preserve)116 void resize_internal (const size_type size, const value_type init, const bool preserve) { 117 if (size != size_) { 118 pointer p_data = data_; 119 if (size) { 120 data_ = alloc_.allocate (size); 121 if (preserve) { 122 pointer si = p_data; 123 pointer di = data_; 124 if (size < size_) { 125 for (; di != data_ + size; ++di) { 126 alloc_.construct (di, *si); 127 ++si; 128 } 129 } 130 else { 131 for (; si != p_data + size_; ++si) { 132 alloc_.construct (di, *si); 133 ++di; 134 } 135 for (; di != data_ + size; ++di) { 136 alloc_.construct (di, init); 137 } 138 } 139 } 140 else { 141 if (! detail::has_trivial_constructor<T>::value) { 142 for (pointer di = data_; di != data_ + size; ++di) 143 alloc_.construct (di, value_type()); 144 } 145 } 146 } 147 148 if (size_) { 149 if (! detail::has_trivial_destructor<T>::value) { 150 for (pointer si = p_data; si != p_data + size_; ++si) 151 alloc_.destroy (si); 152 } 153 alloc_.deallocate (p_data, size_); 154 } 155 156 if (!size) 157 data_ = 0; 158 size_ = size; 159 } 160 } 161 public: 162 BOOST_UBLAS_INLINE resize(size_type size)163 void resize (size_type size) { 164 resize_internal (size, value_type (), false); 165 } 166 BOOST_UBLAS_INLINE resize(size_type size,value_type init)167 void resize (size_type size, value_type init) { 168 resize_internal (size, init, true); 169 } 170 171 // Random Access Container 172 BOOST_UBLAS_INLINE max_size() const173 size_type max_size () const { 174 return ALLOC ().max_size(); 175 } 176 177 BOOST_UBLAS_INLINE empty() const178 bool empty () const { 179 return size_ == 0; 180 } 181 182 BOOST_UBLAS_INLINE size() const183 size_type size () const { 184 return size_; 185 } 186 187 // Element access 188 BOOST_UBLAS_INLINE operator [](size_type i) const189 const_reference operator [] (size_type i) const { 190 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 191 return data_ [i]; 192 } 193 BOOST_UBLAS_INLINE operator [](size_type i)194 reference operator [] (size_type i) { 195 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 196 return data_ [i]; 197 } 198 199 // Assignment 200 BOOST_UBLAS_INLINE operator =(const unbounded_array & a)201 unbounded_array &operator = (const unbounded_array &a) { 202 if (this != &a) { 203 resize (a.size_); 204 std::copy (a.data_, a.data_ + a.size_, data_); 205 } 206 return *this; 207 } 208 BOOST_UBLAS_INLINE assign_temporary(unbounded_array & a)209 unbounded_array &assign_temporary (unbounded_array &a) { 210 swap (a); 211 return *this; 212 } 213 214 // Swapping 215 BOOST_UBLAS_INLINE swap(unbounded_array & a)216 void swap (unbounded_array &a) { 217 if (this != &a) { 218 std::swap (size_, a.size_); 219 std::swap (data_, a.data_); 220 } 221 } 222 BOOST_UBLAS_INLINE swap(unbounded_array & a1,unbounded_array & a2)223 friend void swap (unbounded_array &a1, unbounded_array &a2) { 224 a1.swap (a2); 225 } 226 227 BOOST_UBLAS_INLINE begin() const228 const_iterator begin () const { 229 return data_; 230 } 231 BOOST_UBLAS_INLINE cbegin() const232 const_iterator cbegin () const { 233 return begin (); 234 } 235 BOOST_UBLAS_INLINE end() const236 const_iterator end () const { 237 return data_ + size_; 238 } 239 BOOST_UBLAS_INLINE cend() const240 const_iterator cend () const { 241 return end (); 242 } 243 244 BOOST_UBLAS_INLINE begin()245 iterator begin () { 246 return data_; 247 } 248 BOOST_UBLAS_INLINE end()249 iterator end () { 250 return data_ + size_; 251 } 252 253 // Reverse iterators 254 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 255 typedef std::reverse_iterator<iterator> reverse_iterator; 256 257 BOOST_UBLAS_INLINE rbegin() const258 const_reverse_iterator rbegin () const { 259 return const_reverse_iterator (end ()); 260 } 261 BOOST_UBLAS_INLINE crbegin() const262 const_reverse_iterator crbegin () const { 263 return rbegin (); 264 } 265 BOOST_UBLAS_INLINE rend() const266 const_reverse_iterator rend () const { 267 return const_reverse_iterator (begin ()); 268 } 269 BOOST_UBLAS_INLINE crend() const270 const_reverse_iterator crend () const { 271 return rend (); 272 } 273 BOOST_UBLAS_INLINE rbegin()274 reverse_iterator rbegin () { 275 return reverse_iterator (end ()); 276 } 277 BOOST_UBLAS_INLINE rend()278 reverse_iterator rend () { 279 return reverse_iterator (begin ()); 280 } 281 282 // Allocator get_allocator()283 allocator_type get_allocator () { 284 return alloc_; 285 } 286 287 private: 288 friend class boost::serialization::access; 289 290 // Serialization 291 template<class Archive> serialize(Archive & ar,const unsigned int)292 void serialize(Archive & ar, const unsigned int /*version*/) 293 { 294 serialization::collection_size_type s(size_); 295 ar & serialization::make_nvp("size",s); 296 if ( Archive::is_loading::value ) { 297 resize(s); 298 } 299 ar & serialization::make_array(data_, s); 300 } 301 302 private: 303 // Handle explict destroy on a (possibly indexed) iterator 304 BOOST_UBLAS_INLINE iterator_destroy(iterator & i)305 static void iterator_destroy (iterator &i) { 306 (&(*i)) -> ~value_type (); 307 } 308 ALLOC alloc_; 309 size_type size_; 310 pointer data_; 311 }; 312 313 // Bounded array - with allocator for size_type and difference_type 314 template<class T, std::size_t N, class ALLOC> 315 class bounded_array: 316 public storage_array<bounded_array<T, N, ALLOC> > { 317 318 typedef bounded_array<T, N, ALLOC> self_type; 319 public: 320 // No allocator_type as ALLOC is not used for allocation 321 typedef typename ALLOC::size_type size_type; 322 typedef typename ALLOC::difference_type difference_type; 323 typedef T value_type; 324 typedef const T &const_reference; 325 typedef T &reference; 326 typedef const T *const_pointer; 327 typedef T *pointer; 328 typedef const_pointer const_iterator; 329 typedef pointer iterator; 330 331 // Construction and destruction 332 BOOST_UBLAS_INLINE bounded_array()333 bounded_array (): 334 size_ (0) /*, data_ ()*/ { // size 0 - use bounded_vector to default construct with size N 335 } 336 explicit BOOST_UBLAS_INLINE bounded_array(size_type size)337 bounded_array (size_type size): 338 size_ (size) /*, data_ ()*/ { 339 BOOST_UBLAS_CHECK (size_ <= N, bad_size ()); 340 // data_ (an array) elements are already default constructed 341 } 342 BOOST_UBLAS_INLINE bounded_array(size_type size,const value_type & init)343 bounded_array (size_type size, const value_type &init): 344 size_ (size) /*, data_ ()*/ { 345 BOOST_UBLAS_CHECK (size_ <= N, bad_size ()); 346 // ISSUE elements should be value constructed here, but we must fill instead as already default constructed 347 std::fill (begin(), end(), init) ; 348 } 349 BOOST_UBLAS_INLINE bounded_array(const bounded_array & c)350 bounded_array (const bounded_array &c): 351 size_ (c.size_) { 352 // ISSUE elements should be copy constructed here, but we must copy instead as already default constructed 353 std::copy (c.begin(), c.end(), begin()); 354 } 355 356 // Resizing 357 BOOST_UBLAS_INLINE resize(size_type size)358 void resize (size_type size) { 359 BOOST_UBLAS_CHECK (size <= N, bad_size ()); 360 size_ = size; 361 } 362 BOOST_UBLAS_INLINE resize(size_type size,value_type init)363 void resize (size_type size, value_type init) { 364 BOOST_UBLAS_CHECK (size <= N, bad_size ()); 365 if (size > size_) 366 std::fill (data_ + size_, data_ + size, init); 367 size_ = size; 368 } 369 370 // Random Access Container 371 BOOST_UBLAS_INLINE max_size() const372 size_type max_size () const { 373 return N; 374 } 375 376 BOOST_UBLAS_INLINE empty() const377 bool empty () const { 378 return size_ == 0; 379 } 380 381 BOOST_UBLAS_INLINE size() const382 size_type size () const { 383 return size_; 384 } 385 386 // Element access 387 BOOST_UBLAS_INLINE operator [](size_type i) const388 const_reference operator [] (size_type i) const { 389 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 390 return data_ [i]; 391 } 392 BOOST_UBLAS_INLINE operator [](size_type i)393 reference operator [] (size_type i) { 394 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 395 return data_ [i]; 396 } 397 398 // Assignment 399 BOOST_UBLAS_INLINE operator =(const bounded_array & a)400 bounded_array &operator = (const bounded_array &a) { 401 if (this != &a) { 402 resize (a.size_); 403 std::copy (a.data_, a.data_ + a.size_, data_); 404 } 405 return *this; 406 } 407 BOOST_UBLAS_INLINE assign_temporary(bounded_array & a)408 bounded_array &assign_temporary (bounded_array &a) { 409 *this = a; 410 return *this; 411 } 412 413 // Swapping 414 BOOST_UBLAS_INLINE swap(bounded_array & a)415 void swap (bounded_array &a) { 416 if (this != &a) { 417 std::swap (size_, a.size_); 418 std::swap_ranges (data_, data_ + (std::max) (size_, a.size_), a.data_); 419 } 420 } 421 BOOST_UBLAS_INLINE swap(bounded_array & a1,bounded_array & a2)422 friend void swap (bounded_array &a1, bounded_array &a2) { 423 a1.swap (a2); 424 } 425 426 BOOST_UBLAS_INLINE begin() const427 const_iterator begin () const { 428 return data_; 429 } 430 BOOST_UBLAS_INLINE cbegin() const431 const_iterator cbegin () const { 432 return begin (); 433 } 434 BOOST_UBLAS_INLINE end() const435 const_iterator end () const { 436 return data_ + size_; 437 } 438 BOOST_UBLAS_INLINE cend() const439 const_iterator cend () const { 440 return end (); 441 } 442 443 BOOST_UBLAS_INLINE begin()444 iterator begin () { 445 return data_; 446 } 447 BOOST_UBLAS_INLINE end()448 iterator end () { 449 return data_ + size_; 450 } 451 452 // Reverse iterators 453 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 454 typedef std::reverse_iterator<iterator> reverse_iterator; 455 456 BOOST_UBLAS_INLINE rbegin() const457 const_reverse_iterator rbegin () const { 458 return const_reverse_iterator (end ()); 459 } 460 BOOST_UBLAS_INLINE crbegin() const461 const_reverse_iterator crbegin () const { 462 return rbegin (); 463 } 464 BOOST_UBLAS_INLINE rend() const465 const_reverse_iterator rend () const { 466 return const_reverse_iterator (begin ()); 467 } 468 BOOST_UBLAS_INLINE crend() const469 const_reverse_iterator crend () const { 470 return rend (); 471 } 472 BOOST_UBLAS_INLINE rbegin()473 reverse_iterator rbegin () { 474 return reverse_iterator (end ()); 475 } 476 BOOST_UBLAS_INLINE rend()477 reverse_iterator rend () { 478 return reverse_iterator (begin ()); 479 } 480 481 private: 482 // Serialization 483 friend class boost::serialization::access; 484 485 template<class Archive> serialize(Archive & ar,const unsigned int)486 void serialize(Archive & ar, const unsigned int /*version*/) 487 { 488 serialization::collection_size_type s(size_); 489 ar & serialization::make_nvp("size", s); 490 if ( Archive::is_loading::value ) { 491 if (s > N) bad_size("too large size in bounded_array::load()\n").raise(); 492 resize(s); 493 } 494 ar & serialization::make_array(data_, s); 495 } 496 497 private: 498 size_type size_; 499 // MSVC does not like arrays of size 0 in base classes. Hence, this conditionally changes the size to 1 500 #ifdef _MSC_VER 501 BOOST_UBLAS_BOUNDED_ARRAY_ALIGN value_type data_ [(N>0)?N:1]; 502 #else 503 BOOST_UBLAS_BOUNDED_ARRAY_ALIGN value_type data_ [N]; 504 #endif 505 }; 506 507 508 // Array adaptor with normal deep copy semantics of elements 509 template<class T> 510 class array_adaptor: 511 public storage_array<array_adaptor<T> > { 512 513 typedef array_adaptor<T> self_type; 514 public: 515 typedef std::size_t size_type; 516 typedef std::ptrdiff_t difference_type; 517 typedef T value_type; 518 typedef const T &const_reference; 519 typedef T &reference; 520 typedef const T *const_pointer; 521 typedef T *pointer; 522 523 // Construction and destruction 524 BOOST_UBLAS_INLINE array_adaptor()525 array_adaptor (): 526 size_ (0), own_ (true), data_ (new value_type [0]) { 527 } 528 explicit BOOST_UBLAS_INLINE array_adaptor(size_type size)529 array_adaptor (size_type size): 530 size_ (size), own_ (true), data_ (new value_type [size]) { 531 } 532 BOOST_UBLAS_INLINE array_adaptor(size_type size,const value_type & init)533 array_adaptor (size_type size, const value_type &init): 534 size_ (size), own_ (true), data_ (new value_type [size]) { 535 std::fill (data_, data_ + size_, init); 536 } 537 BOOST_UBLAS_INLINE array_adaptor(size_type size,pointer data)538 array_adaptor (size_type size, pointer data): 539 size_ (size), own_ (false), data_ (data) {} 540 541 template <size_t N> array_adaptor(T (& data)[N])542 BOOST_UBLAS_INLINE array_adaptor (T (&data)[N]): 543 size_ (N), own_ (false), data_ (data) {} 544 BOOST_UBLAS_INLINE array_adaptor(const array_adaptor & a)545 array_adaptor (const array_adaptor &a): 546 storage_array<self_type> (), 547 size_ (a.size_), own_ (true), data_ (new value_type [a.size_]) { 548 *this = a; 549 } 550 BOOST_UBLAS_INLINE ~array_adaptor()551 ~array_adaptor () { 552 if (own_) { 553 delete [] data_; 554 } 555 } 556 557 // Resizing 558 private: 559 BOOST_UBLAS_INLINE resize_internal(size_type size,value_type init,bool preserve=true)560 void resize_internal (size_type size, value_type init, bool preserve = true) { 561 if (size != size_) { 562 pointer data = new value_type [size]; 563 if (preserve) { 564 std::copy (data_, data_ + (std::min) (size, size_), data); 565 std::fill (data + (std::min) (size, size_), data + size, init); 566 } 567 if (own_) 568 delete [] data_; 569 size_ = size; 570 own_ = true; 571 data_ = data; 572 } 573 } 574 BOOST_UBLAS_INLINE resize_internal(size_type size,pointer data,value_type init,bool preserve=true)575 void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) { 576 if (data != data_) { 577 if (preserve) { 578 std::copy (data_, data_ + (std::min) (size, size_), data); 579 std::fill (data + (std::min) (size, size_), data + size, init); 580 } 581 if (own_) 582 delete [] data_; 583 own_ = false; 584 data_ = data; 585 } 586 else { 587 std::fill (data + (std::min) (size, size_), data + size, init); 588 } 589 size_ = size; 590 } 591 public: 592 BOOST_UBLAS_INLINE resize(size_type size)593 void resize (size_type size) { 594 resize_internal (size, value_type (), false); 595 } 596 BOOST_UBLAS_INLINE resize(size_type size,value_type init)597 void resize (size_type size, value_type init) { 598 resize_internal (size, init, true); 599 } 600 BOOST_UBLAS_INLINE resize(size_type size,pointer data)601 void resize (size_type size, pointer data) { 602 resize_internal (size, data, value_type (), false); 603 } 604 BOOST_UBLAS_INLINE resize(size_type size,pointer data,value_type init)605 void resize (size_type size, pointer data, value_type init) { 606 resize_internal (size, data, init, true); 607 } 608 609 template <size_t N> resize(T (& data)[N])610 BOOST_UBLAS_INLINE void resize (T (&data)[N]) { 611 resize_internal (N, data, value_type (), false); 612 } 613 614 template <size_t N> resize(T (& data)[N],value_type init)615 BOOST_UBLAS_INLINE void resize (T (&data)[N], value_type init) { 616 resize_internal (N, data, init, true); 617 } 618 619 BOOST_UBLAS_INLINE size() const620 size_type size () const { 621 return size_; 622 } 623 624 // Element access 625 BOOST_UBLAS_INLINE operator [](size_type i) const626 const_reference operator [] (size_type i) const { 627 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 628 return data_ [i]; 629 } 630 BOOST_UBLAS_INLINE operator [](size_type i)631 reference operator [] (size_type i) { 632 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 633 return data_ [i]; 634 } 635 636 // Assignment 637 BOOST_UBLAS_INLINE operator =(const array_adaptor & a)638 array_adaptor &operator = (const array_adaptor &a) { 639 if (this != &a) { 640 resize (a.size_); 641 std::copy (a.data_, a.data_ + a.size_, data_); 642 } 643 return *this; 644 } 645 BOOST_UBLAS_INLINE assign_temporary(array_adaptor & a)646 array_adaptor &assign_temporary (array_adaptor &a) { 647 if (own_ && a.own_) 648 swap (a); 649 else 650 *this = a; 651 return *this; 652 } 653 654 // Swapping 655 BOOST_UBLAS_INLINE swap(array_adaptor & a)656 void swap (array_adaptor &a) { 657 if (this != &a) { 658 std::swap (size_, a.size_); 659 std::swap (own_, a.own_); 660 std::swap (data_, a.data_); 661 } 662 } 663 BOOST_UBLAS_INLINE swap(array_adaptor & a1,array_adaptor & a2)664 friend void swap (array_adaptor &a1, array_adaptor &a2) { 665 a1.swap (a2); 666 } 667 668 // Iterators simply are pointers. 669 670 typedef const_pointer const_iterator; 671 672 BOOST_UBLAS_INLINE begin() const673 const_iterator begin () const { 674 return data_; 675 } 676 BOOST_UBLAS_INLINE cbegin() const677 const_iterator cbegin () const { 678 return begin (); 679 } 680 BOOST_UBLAS_INLINE end() const681 const_iterator end () const { 682 return data_ + size_; 683 } 684 BOOST_UBLAS_INLINE cend() const685 const_iterator cend () const { 686 return end (); 687 } 688 689 typedef pointer iterator; 690 691 BOOST_UBLAS_INLINE begin()692 iterator begin () { 693 return data_; 694 } 695 BOOST_UBLAS_INLINE end()696 iterator end () { 697 return data_ + size_; 698 } 699 700 // Reverse iterators 701 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 702 typedef std::reverse_iterator<iterator> reverse_iterator; 703 704 BOOST_UBLAS_INLINE rbegin() const705 const_reverse_iterator rbegin () const { 706 return const_reverse_iterator (end ()); 707 } 708 BOOST_UBLAS_INLINE crbegin() const709 const_reverse_iterator crbegin () const { 710 return rbegin (); 711 } 712 BOOST_UBLAS_INLINE rend() const713 const_reverse_iterator rend () const { 714 return const_reverse_iterator (begin ()); 715 } 716 BOOST_UBLAS_INLINE crend() const717 const_reverse_iterator crend () const { 718 return rend (); 719 } 720 BOOST_UBLAS_INLINE rbegin()721 reverse_iterator rbegin () { 722 return reverse_iterator (end ()); 723 } 724 BOOST_UBLAS_INLINE rend()725 reverse_iterator rend () { 726 return reverse_iterator (begin ()); 727 } 728 729 private: 730 size_type size_; 731 bool own_; 732 pointer data_; 733 }; 734 735 #ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR 736 // Array adaptor with shallow (reference) copy semantics of elements. 737 // shared_array is used to maintain reference counts. 738 // This class breaks the normal copy semantics for a storage container and is very dangerous! 739 template<class T> 740 class shallow_array_adaptor: 741 public storage_array<shallow_array_adaptor<T> > { 742 743 typedef shallow_array_adaptor<T> self_type; 744 745 template<class TT> 746 struct leaker { 747 typedef void result_type; 748 typedef TT *argument_type; 749 750 BOOST_UBLAS_INLINE operator ()boost::numeric::ublas::shallow_array_adaptor::leaker751 result_type operator () (argument_type /* x */) {} 752 }; 753 754 public: 755 typedef std::size_t size_type; 756 typedef std::ptrdiff_t difference_type; 757 typedef T value_type; 758 typedef const T &const_reference; 759 typedef T &reference; 760 typedef const T *const_pointer; 761 typedef T *pointer; 762 763 // Construction and destruction 764 BOOST_UBLAS_INLINE shallow_array_adaptor()765 shallow_array_adaptor (): 766 size_ (0), own_ (true), data_ (new value_type [0]) { 767 } 768 explicit BOOST_UBLAS_INLINE shallow_array_adaptor(size_type size)769 shallow_array_adaptor (size_type size): 770 size_ (size), own_ (true), data_ (new value_type [size]) { 771 } 772 BOOST_UBLAS_INLINE shallow_array_adaptor(size_type size,const value_type & init)773 shallow_array_adaptor (size_type size, const value_type &init): 774 size_ (size), own_ (true), data_ (new value_type [size]) { 775 std::fill (data_.get (), data_.get () + size_, init); 776 } 777 BOOST_UBLAS_INLINE shallow_array_adaptor(size_type size,pointer data)778 shallow_array_adaptor (size_type size, pointer data): 779 size_ (size), own_ (false), data_ (data, leaker<value_type> ()) {} 780 template <size_t N> 781 BOOST_UBLAS_INLINE shallow_array_adaptor(T (& data)[N])782 shallow_array_adaptor (T (&data)[N]): 783 size_ (N), own_ (false), data_ (data, leaker<value_type> ()) {} 784 785 BOOST_UBLAS_INLINE shallow_array_adaptor(const shallow_array_adaptor & a)786 shallow_array_adaptor (const shallow_array_adaptor &a): 787 storage_array<self_type> (), 788 size_ (a.size_), own_ (a.own_), data_ (a.data_) {} 789 790 BOOST_UBLAS_INLINE ~shallow_array_adaptor()791 ~shallow_array_adaptor () { 792 } 793 794 // Resizing 795 private: 796 BOOST_UBLAS_INLINE resize_internal(size_type size,value_type init,bool preserve=true)797 void resize_internal (size_type size, value_type init, bool preserve = true) { 798 if (size != size_) { 799 shared_array<value_type> data (new value_type [size]); 800 if (preserve) { 801 std::copy (data_.get (), data_.get () + (std::min) (size, size_), data.get ()); 802 std::fill (data.get () + (std::min) (size, size_), data.get () + size, init); 803 } 804 size_ = size; 805 own_ = true; 806 data_ = data; 807 } 808 } 809 BOOST_UBLAS_INLINE resize_internal(size_type size,pointer data,value_type init,bool preserve=true)810 void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) { 811 if (preserve) { 812 std::copy (data_.get (), data_.get () + (std::min) (size, size_), data); 813 std::fill (data + (std::min) (size, size_), data + size, init); 814 } 815 size_ = size; 816 own_ = false; 817 data_.reset(data, leaker<value_type> ()); 818 } 819 public: 820 BOOST_UBLAS_INLINE resize(size_type size)821 void resize (size_type size) { 822 resize_internal (size, value_type (), false); 823 } 824 BOOST_UBLAS_INLINE resize(size_type size,value_type init)825 void resize (size_type size, value_type init) { 826 resize_internal (size, init, true); 827 } 828 BOOST_UBLAS_INLINE resize(size_type size,pointer data)829 void resize (size_type size, pointer data) { 830 resize_internal (size, data, value_type (), false); 831 } 832 BOOST_UBLAS_INLINE resize(size_type size,pointer data,value_type init)833 void resize (size_type size, pointer data, value_type init) { 834 resize_internal (size, data, init, true); 835 } 836 template <size_t N> 837 BOOST_UBLAS_INLINE resize(T (& data)[N])838 void resize (T (&data)[N]) { 839 resize_internal (N, data, value_type (), false); 840 } 841 template <size_t N> 842 BOOST_UBLAS_INLINE resize(T (& data)[N],value_type init)843 void resize (T (&data)[N], value_type init) { 844 resize_internal (N, data, init, true); 845 } 846 847 BOOST_UBLAS_INLINE size() const848 size_type size () const { 849 return size_; 850 } 851 852 // Element access 853 BOOST_UBLAS_INLINE operator [](size_type i) const854 const_reference operator [] (size_type i) const { 855 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 856 return data_ [i]; 857 } 858 BOOST_UBLAS_INLINE operator [](size_type i)859 reference operator [] (size_type i) { 860 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 861 return data_ [i]; 862 } 863 864 // Assignment 865 BOOST_UBLAS_INLINE operator =(const shallow_array_adaptor & a)866 shallow_array_adaptor &operator = (const shallow_array_adaptor &a) { 867 if (this != &a) { 868 resize (a.size_); 869 std::copy (a.data_.get (), a.data_.get () + a.size_, data_.get ()); 870 } 871 return *this; 872 } 873 BOOST_UBLAS_INLINE assign_temporary(shallow_array_adaptor & a)874 shallow_array_adaptor &assign_temporary (shallow_array_adaptor &a) { 875 if (own_ && a.own_) 876 swap (a); 877 else 878 *this = a; 879 return *this; 880 } 881 882 // Swapping 883 BOOST_UBLAS_INLINE swap(shallow_array_adaptor & a)884 void swap (shallow_array_adaptor &a) { 885 if (this != &a) { 886 std::swap (size_, a.size_); 887 std::swap (own_, a.own_); 888 std::swap (data_, a.data_); 889 } 890 } 891 BOOST_UBLAS_INLINE swap(shallow_array_adaptor & a1,shallow_array_adaptor & a2)892 friend void swap (shallow_array_adaptor &a1, shallow_array_adaptor &a2) { 893 a1.swap (a2); 894 } 895 896 // Iterators simply are pointers. 897 898 typedef const_pointer const_iterator; 899 900 BOOST_UBLAS_INLINE begin() const901 const_iterator begin () const { 902 return data_.get (); 903 } 904 BOOST_UBLAS_INLINE cbegin() const905 const_iterator cbegin () const { 906 return begin (); 907 } 908 BOOST_UBLAS_INLINE end() const909 const_iterator end () const { 910 return data_.get () + size_; 911 } 912 BOOST_UBLAS_INLINE cend() const913 const_iterator cend () const { 914 return end (); 915 } 916 917 typedef pointer iterator; 918 919 BOOST_UBLAS_INLINE begin()920 iterator begin () { 921 return data_.get (); 922 } 923 BOOST_UBLAS_INLINE end()924 iterator end () { 925 return data_.get () + size_; 926 } 927 928 // Reverse iterators 929 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 930 typedef std::reverse_iterator<iterator> reverse_iterator; 931 932 BOOST_UBLAS_INLINE rbegin() const933 const_reverse_iterator rbegin () const { 934 return const_reverse_iterator (end ()); 935 } 936 BOOST_UBLAS_INLINE crbegin() const937 const_reverse_iterator crbegin () const { 938 return rbegin (); 939 } 940 BOOST_UBLAS_INLINE rend() const941 const_reverse_iterator rend () const { 942 return const_reverse_iterator (begin ()); 943 } 944 BOOST_UBLAS_INLINE crend() const945 const_reverse_iterator crend () const { 946 return rend (); 947 } 948 BOOST_UBLAS_INLINE rbegin()949 reverse_iterator rbegin () { 950 return reverse_iterator (end ()); 951 } 952 BOOST_UBLAS_INLINE rend()953 reverse_iterator rend () { 954 return reverse_iterator (begin ()); 955 } 956 957 private: 958 size_type size_; 959 bool own_; 960 shared_array<value_type> data_; 961 }; 962 963 #endif 964 965 966 // Range class 967 template <class Z, class D> 968 class basic_range { 969 typedef basic_range<Z, D> self_type; 970 public: 971 typedef Z size_type; 972 typedef D difference_type; 973 typedef size_type value_type; 974 typedef value_type const_reference; 975 typedef const_reference reference; 976 typedef const value_type *const_pointer; 977 typedef value_type *pointer; 978 979 // Construction and destruction 980 BOOST_UBLAS_INLINE basic_range()981 basic_range (): 982 start_ (0), size_ (0) {} 983 BOOST_UBLAS_INLINE basic_range(size_type start,size_type stop)984 basic_range (size_type start, size_type stop): 985 start_ (start), size_ (stop - start) { 986 BOOST_UBLAS_CHECK (start_ <= stop, bad_index ()); 987 } 988 989 BOOST_UBLAS_INLINE start() const990 size_type start () const { 991 return start_; 992 } 993 BOOST_UBLAS_INLINE size() const994 size_type size () const { 995 return size_; 996 } 997 998 // Random Access Container 999 BOOST_UBLAS_INLINE max_size() const1000 size_type max_size () const { 1001 return size_; 1002 } 1003 1004 BOOST_UBLAS_INLINE empty() const1005 bool empty () const { 1006 return size_ == 0; 1007 } 1008 1009 // Element access 1010 BOOST_UBLAS_INLINE operator ()(size_type i) const1011 const_reference operator () (size_type i) const { 1012 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 1013 return start_ + i; 1014 } 1015 1016 // Composition 1017 BOOST_UBLAS_INLINE compose(const basic_range & r) const1018 basic_range compose (const basic_range &r) const { 1019 return basic_range (start_ + r.start_, start_ + r.start_ + r.size_); 1020 } 1021 1022 // Comparison 1023 BOOST_UBLAS_INLINE operator ==(const basic_range & r) const1024 bool operator == (const basic_range &r) const { 1025 return start_ == r.start_ && size_ == r.size_; 1026 } 1027 BOOST_UBLAS_INLINE operator !=(const basic_range & r) const1028 bool operator != (const basic_range &r) const { 1029 return ! (*this == r); 1030 } 1031 1032 // Iterator types 1033 private: 1034 // Use and index 1035 typedef size_type const_subiterator_type; 1036 1037 public: 1038 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1039 typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator; 1040 #else 1041 class const_iterator: 1042 public container_const_reference<basic_range>, 1043 public random_access_iterator_base<std::random_access_iterator_tag, 1044 const_iterator, value_type> { 1045 public: 1046 typedef typename basic_range::value_type value_type; 1047 typedef typename basic_range::difference_type difference_type; 1048 typedef typename basic_range::const_reference reference; 1049 typedef typename basic_range::const_pointer pointer; 1050 1051 // Construction and destruction 1052 BOOST_UBLAS_INLINE 1053 const_iterator (): 1054 container_const_reference<basic_range> (), it_ () {} 1055 BOOST_UBLAS_INLINE 1056 const_iterator (const basic_range &r, const const_subiterator_type &it): 1057 container_const_reference<basic_range> (r), it_ (it) {} 1058 1059 // Arithmetic 1060 BOOST_UBLAS_INLINE 1061 const_iterator &operator ++ () { 1062 ++ it_; 1063 return *this; 1064 } 1065 BOOST_UBLAS_INLINE 1066 const_iterator &operator -- () { 1067 BOOST_UBLAS_CHECK (it_ > 0, bad_index ()); 1068 -- it_; 1069 return *this; 1070 } 1071 BOOST_UBLAS_INLINE 1072 const_iterator &operator += (difference_type n) { 1073 BOOST_UBLAS_CHECK (n >= 0 || it_ >= size_type(-n), bad_index ()); 1074 it_ += n; 1075 return *this; 1076 } 1077 BOOST_UBLAS_INLINE 1078 const_iterator &operator -= (difference_type n) { 1079 BOOST_UBLAS_CHECK (n <= 0 || it_ >= size_type(n), bad_index ()); 1080 it_ -= n; 1081 return *this; 1082 } 1083 BOOST_UBLAS_INLINE 1084 difference_type operator - (const const_iterator &it) const { 1085 return it_ - it.it_; 1086 } 1087 1088 // Dereference 1089 BOOST_UBLAS_INLINE 1090 const_reference operator * () const { 1091 BOOST_UBLAS_CHECK ((*this) ().start () <= it_, bad_index ()); 1092 BOOST_UBLAS_CHECK (it_ < (*this) ().start () + (*this) ().size (), bad_index ()); 1093 return it_; 1094 } 1095 1096 BOOST_UBLAS_INLINE 1097 const_reference operator [] (difference_type n) const { 1098 return *(*this + n); 1099 } 1100 1101 // Index 1102 BOOST_UBLAS_INLINE 1103 size_type index () const { 1104 BOOST_UBLAS_CHECK ((*this) ().start () <= it_, bad_index ()); 1105 BOOST_UBLAS_CHECK (it_ < (*this) ().start () + (*this) ().size (), bad_index ()); 1106 return it_ - (*this) ().start (); 1107 } 1108 1109 // Assignment 1110 BOOST_UBLAS_INLINE 1111 const_iterator &operator = (const const_iterator &it) { 1112 // Comeau recommends... 1113 this->assign (&it ()); 1114 it_ = it.it_; 1115 return *this; 1116 } 1117 1118 // Comparison 1119 BOOST_UBLAS_INLINE 1120 bool operator == (const const_iterator &it) const { 1121 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 1122 return it_ == it.it_; 1123 } 1124 BOOST_UBLAS_INLINE 1125 bool operator < (const const_iterator &it) const { 1126 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 1127 return it_ < it.it_; 1128 } 1129 1130 private: 1131 const_subiterator_type it_; 1132 }; 1133 #endif 1134 1135 BOOST_UBLAS_INLINE begin() const1136 const_iterator begin () const { 1137 return const_iterator (*this, start_); 1138 } 1139 BOOST_UBLAS_INLINE cbegin() const1140 const_iterator cbegin () const { 1141 return begin (); 1142 } 1143 BOOST_UBLAS_INLINE end() const1144 const_iterator end () const { 1145 return const_iterator (*this, start_ + size_); 1146 } 1147 BOOST_UBLAS_INLINE cend() const1148 const_iterator cend () const { 1149 return end (); 1150 } 1151 1152 // Reverse iterator 1153 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 1154 1155 BOOST_UBLAS_INLINE rbegin() const1156 const_reverse_iterator rbegin () const { 1157 return const_reverse_iterator (end ()); 1158 } 1159 BOOST_UBLAS_INLINE crbegin() const1160 const_reverse_iterator crbegin () const { 1161 return rbegin (); 1162 } 1163 BOOST_UBLAS_INLINE rend() const1164 const_reverse_iterator rend () const { 1165 return const_reverse_iterator (begin ()); 1166 } 1167 BOOST_UBLAS_INLINE crend() const1168 const_reverse_iterator crend () const { 1169 return rend (); 1170 } 1171 1172 BOOST_UBLAS_INLINE preprocess(size_type size) const1173 basic_range preprocess (size_type size) const { 1174 if (this != &all_) 1175 return *this; 1176 return basic_range (0, size); 1177 } 1178 static 1179 BOOST_UBLAS_INLINE all()1180 const basic_range &all () { 1181 return all_; 1182 } 1183 1184 private: 1185 size_type start_; 1186 size_type size_; 1187 static const basic_range all_; 1188 }; 1189 1190 template <class Z, class D> 1191 const basic_range<Z,D> basic_range<Z,D>::all_ (0, size_type (-1)); 1192 1193 1194 // Slice class 1195 template <class Z, class D> 1196 class basic_slice { 1197 typedef basic_slice<Z, D> self_type; 1198 public: 1199 typedef Z size_type; 1200 typedef D difference_type; 1201 typedef size_type value_type; 1202 typedef value_type const_reference; 1203 typedef const_reference reference; 1204 typedef const value_type *const_pointer; 1205 typedef value_type *pointer; 1206 1207 // Construction and destruction 1208 BOOST_UBLAS_INLINE basic_slice()1209 basic_slice (): 1210 start_ (0), stride_ (0), size_ (0) {} 1211 BOOST_UBLAS_INLINE basic_slice(size_type start,difference_type stride,size_type size)1212 basic_slice (size_type start, difference_type stride, size_type size): 1213 start_ (start), stride_ (stride), size_ (size) {} 1214 1215 BOOST_UBLAS_INLINE start() const1216 size_type start () const { 1217 return start_; 1218 } 1219 BOOST_UBLAS_INLINE stride() const1220 difference_type stride () const { 1221 return stride_; 1222 } 1223 BOOST_UBLAS_INLINE size() const1224 size_type size () const { 1225 return size_; 1226 } 1227 1228 // Random Access Container 1229 BOOST_UBLAS_INLINE max_size() const1230 size_type max_size () const { 1231 return size_; 1232 } 1233 1234 BOOST_UBLAS_INLINE empty() const1235 bool empty () const { 1236 return size_ == 0; 1237 } 1238 1239 // Element access 1240 BOOST_UBLAS_INLINE operator ()(size_type i) const1241 const_reference operator () (size_type i) const { 1242 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 1243 BOOST_UBLAS_CHECK (stride_ >= 0 || start_ >= i * -stride_, bad_index ()); 1244 return start_ + i * stride_; 1245 } 1246 1247 // Composition 1248 BOOST_UBLAS_INLINE compose(const basic_range<size_type,difference_type> & r) const1249 basic_slice compose (const basic_range<size_type, difference_type> &r) const { 1250 BOOST_UBLAS_CHECK (stride_ >=0 || start_ >= -stride_ * r.start(), bad_index ()); 1251 return basic_slice (start_ + stride_ * r.start (), stride_, r.size ()); 1252 } 1253 BOOST_UBLAS_INLINE compose(const basic_slice & s) const1254 basic_slice compose (const basic_slice &s) const { 1255 BOOST_UBLAS_CHECK (stride_ >=0 || start_ >= -stride_ * s.start_, bad_index ()); 1256 return basic_slice (start_ + stride_ * s.start_, stride_ * s.stride_, s.size_); 1257 } 1258 1259 // Comparison 1260 BOOST_UBLAS_INLINE operator ==(const basic_slice & s) const1261 bool operator == (const basic_slice &s) const { 1262 return start_ == s.start_ && stride_ == s.stride_ && size_ == s.size_; 1263 } 1264 BOOST_UBLAS_INLINE operator !=(const basic_slice & s) const1265 bool operator != (const basic_slice &s) const { 1266 return ! (*this == s); 1267 } 1268 1269 // Iterator types 1270 private: 1271 // Use and index 1272 typedef size_type const_subiterator_type; 1273 1274 public: 1275 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1276 typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator; 1277 #else 1278 class const_iterator: 1279 public container_const_reference<basic_slice>, 1280 public random_access_iterator_base<std::random_access_iterator_tag, 1281 const_iterator, value_type> { 1282 public: 1283 typedef typename basic_slice::value_type value_type; 1284 typedef typename basic_slice::difference_type difference_type; 1285 typedef typename basic_slice::const_reference reference; 1286 typedef typename basic_slice::const_pointer pointer; 1287 1288 // Construction and destruction 1289 BOOST_UBLAS_INLINE 1290 const_iterator (): 1291 container_const_reference<basic_slice> (), it_ () {} 1292 BOOST_UBLAS_INLINE 1293 const_iterator (const basic_slice &s, const const_subiterator_type &it): 1294 container_const_reference<basic_slice> (s), it_ (it) {} 1295 1296 // Arithmetic 1297 BOOST_UBLAS_INLINE 1298 const_iterator &operator ++ () { 1299 ++it_; 1300 return *this; 1301 } 1302 BOOST_UBLAS_INLINE 1303 const_iterator &operator -- () { 1304 BOOST_UBLAS_CHECK (it_ > 0, bad_index ()); 1305 --it_; 1306 return *this; 1307 } 1308 BOOST_UBLAS_INLINE 1309 const_iterator &operator += (difference_type n) { 1310 BOOST_UBLAS_CHECK (n >= 0 || it_ >= size_type(-n), bad_index ()); 1311 it_ += n; 1312 return *this; 1313 } 1314 BOOST_UBLAS_INLINE 1315 const_iterator &operator -= (difference_type n) { 1316 BOOST_UBLAS_CHECK (n <= 0 || it_ >= size_type(n), bad_index ()); 1317 it_ -= n; 1318 return *this; 1319 } 1320 BOOST_UBLAS_INLINE 1321 difference_type operator - (const const_iterator &it) const { 1322 return it_ - it.it_; 1323 } 1324 1325 // Dereference 1326 BOOST_UBLAS_INLINE 1327 const_reference operator * () const { 1328 BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ()); 1329 return (*this) ().start () + it_* (*this) ().stride (); 1330 } 1331 1332 BOOST_UBLAS_INLINE 1333 const_reference operator [] (difference_type n) const { 1334 return *(*this + n); 1335 } 1336 1337 // Index 1338 BOOST_UBLAS_INLINE 1339 size_type index () const { 1340 BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ()); 1341 return it_; 1342 } 1343 1344 // Assignment 1345 BOOST_UBLAS_INLINE 1346 const_iterator &operator = (const const_iterator &it) { 1347 // Comeau recommends... 1348 this->assign (&it ()); 1349 it_ = it.it_; 1350 return *this; 1351 } 1352 1353 // Comparison 1354 BOOST_UBLAS_INLINE 1355 bool operator == (const const_iterator &it) const { 1356 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 1357 return it_ == it.it_; 1358 } 1359 BOOST_UBLAS_INLINE 1360 bool operator < (const const_iterator &it) const { 1361 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 1362 return it_ < it.it_; 1363 } 1364 1365 private: 1366 const_subiterator_type it_; 1367 }; 1368 #endif 1369 1370 BOOST_UBLAS_INLINE begin() const1371 const_iterator begin () const { 1372 return const_iterator (*this, 0); 1373 } 1374 BOOST_UBLAS_INLINE cbegin() const1375 const_iterator cbegin () const { 1376 return begin (); 1377 } 1378 BOOST_UBLAS_INLINE end() const1379 const_iterator end () const { 1380 return const_iterator (*this, size_); 1381 } 1382 BOOST_UBLAS_INLINE cend() const1383 const_iterator cend () const { 1384 return end (); 1385 } 1386 1387 // Reverse iterator 1388 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 1389 1390 BOOST_UBLAS_INLINE rbegin() const1391 const_reverse_iterator rbegin () const { 1392 return const_reverse_iterator (end ()); 1393 } 1394 BOOST_UBLAS_INLINE crbegin() const1395 const_reverse_iterator crbegin () const { 1396 return rbegin (); 1397 } 1398 BOOST_UBLAS_INLINE rend() const1399 const_reverse_iterator rend () const { 1400 return const_reverse_iterator (begin ()); 1401 } 1402 BOOST_UBLAS_INLINE crend() const1403 const_reverse_iterator crend () const { 1404 return rend (); 1405 } 1406 1407 BOOST_UBLAS_INLINE preprocess(size_type size) const1408 basic_slice preprocess (size_type size) const { 1409 if (this != &all_) 1410 return *this; 1411 return basic_slice (0, 1, size); 1412 } 1413 static 1414 BOOST_UBLAS_INLINE all()1415 const basic_slice &all () { 1416 return all_; 1417 } 1418 1419 private: 1420 size_type start_; 1421 difference_type stride_; 1422 size_type size_; 1423 static const basic_slice all_; 1424 }; 1425 1426 template <class Z, class D> 1427 const basic_slice<Z,D> basic_slice<Z,D>::all_ (0, 1, size_type (-1)); 1428 1429 1430 // Indirect array class 1431 template<class A> 1432 class indirect_array { 1433 typedef indirect_array<A> self_type; 1434 public: 1435 typedef A array_type; 1436 typedef const A const_array_type; 1437 typedef typename A::size_type size_type; 1438 typedef typename A::difference_type difference_type; 1439 typedef typename A::value_type value_type; 1440 typedef typename A::const_reference const_reference; 1441 typedef typename A::reference reference; 1442 typedef typename A::const_pointer const_pointer; 1443 typedef typename A::pointer pointer; 1444 1445 // Construction and destruction 1446 BOOST_UBLAS_INLINE indirect_array()1447 indirect_array (): 1448 size_ (), data_ () {} 1449 explicit BOOST_UBLAS_INLINE indirect_array(size_type size)1450 indirect_array (size_type size): 1451 size_ (size), data_ (size) {} 1452 BOOST_UBLAS_INLINE indirect_array(size_type size,const array_type & data)1453 indirect_array (size_type size, const array_type &data): 1454 size_ (size), data_ (data) {} 1455 BOOST_UBLAS_INLINE indirect_array(pointer start,pointer stop)1456 indirect_array (pointer start, pointer stop): 1457 size_ (stop - start), data_ (stop - start) { 1458 std::copy (start, stop, data_.begin ()); 1459 } 1460 1461 BOOST_UBLAS_INLINE size() const1462 size_type size () const { 1463 return size_; 1464 } 1465 BOOST_UBLAS_INLINE data() const1466 const_array_type data () const { 1467 return data_; 1468 } 1469 BOOST_UBLAS_INLINE data()1470 array_type data () { 1471 return data_; 1472 } 1473 1474 // Random Access Container 1475 BOOST_UBLAS_INLINE max_size() const1476 size_type max_size () const { 1477 return size_; 1478 } 1479 1480 BOOST_UBLAS_INLINE empty() const1481 bool empty () const { 1482 return data_.size () == 0; 1483 } 1484 1485 // Element access 1486 BOOST_UBLAS_INLINE operator ()(size_type i) const1487 const_reference operator () (size_type i) const { 1488 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 1489 return data_ [i]; 1490 } 1491 BOOST_UBLAS_INLINE operator ()(size_type i)1492 reference operator () (size_type i) { 1493 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 1494 return data_ [i]; 1495 } 1496 1497 BOOST_UBLAS_INLINE operator [](size_type i) const1498 const_reference operator [] (size_type i) const { 1499 return (*this) (i); 1500 } 1501 BOOST_UBLAS_INLINE operator [](size_type i)1502 reference operator [] (size_type i) { 1503 return (*this) (i); 1504 } 1505 1506 // Composition 1507 BOOST_UBLAS_INLINE compose(const basic_range<size_type,difference_type> & r) const1508 indirect_array compose (const basic_range<size_type, difference_type> &r) const { 1509 BOOST_UBLAS_CHECK (r.start () + r.size () <= size_, bad_size ()); 1510 array_type data (r.size ()); 1511 for (size_type i = 0; i < r.size (); ++ i) 1512 data [i] = data_ [r.start () + i]; 1513 return indirect_array (r.size (), data); 1514 } 1515 BOOST_UBLAS_INLINE compose(const basic_slice<size_type,difference_type> & s) const1516 indirect_array compose (const basic_slice<size_type, difference_type> &s) const { 1517 BOOST_UBLAS_CHECK (s.start () + s.stride () * (s.size () - (s.size () > 0)) <= size (), bad_size ()); 1518 array_type data (s.size ()); 1519 for (size_type i = 0; i < s.size (); ++ i) 1520 data [i] = data_ [s.start () + s.stride () * i]; 1521 return indirect_array (s.size (), data); 1522 } 1523 BOOST_UBLAS_INLINE compose(const indirect_array & ia) const1524 indirect_array compose (const indirect_array &ia) const { 1525 array_type data (ia.size_); 1526 for (size_type i = 0; i < ia.size_; ++ i) { 1527 BOOST_UBLAS_CHECK (ia.data_ [i] <= size_, bad_size ()); 1528 data [i] = data_ [ia.data_ [i]]; 1529 } 1530 return indirect_array (ia.size_, data); 1531 } 1532 1533 // Comparison 1534 template<class OA> 1535 BOOST_UBLAS_INLINE operator ==(const indirect_array<OA> & ia) const1536 bool operator == (const indirect_array<OA> &ia) const { 1537 if (size_ != ia.size_) 1538 return false; 1539 for (size_type i = 0; i < BOOST_UBLAS_SAME (size_, ia.size_); ++ i) 1540 if (data_ [i] != ia.data_ [i]) 1541 return false; 1542 return true; 1543 } 1544 template<class OA> 1545 BOOST_UBLAS_INLINE operator !=(const indirect_array<OA> & ia) const1546 bool operator != (const indirect_array<OA> &ia) const { 1547 return ! (*this == ia); 1548 } 1549 1550 // Iterator types 1551 private: 1552 // Use a index difference 1553 typedef difference_type const_subiterator_type; 1554 1555 public: 1556 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1557 typedef indexed_const_iterator<indirect_array, std::random_access_iterator_tag> const_iterator; 1558 #else 1559 class const_iterator: 1560 public container_const_reference<indirect_array>, 1561 public random_access_iterator_base<std::random_access_iterator_tag, 1562 const_iterator, value_type> { 1563 public: 1564 typedef typename indirect_array::value_type value_type; 1565 typedef typename indirect_array::difference_type difference_type; 1566 typedef typename indirect_array::const_reference reference; 1567 typedef typename indirect_array::const_pointer pointer; 1568 1569 // Construction and destruction 1570 BOOST_UBLAS_INLINE 1571 const_iterator (): 1572 container_const_reference<indirect_array> (), it_ () {} 1573 BOOST_UBLAS_INLINE 1574 const_iterator (const indirect_array &ia, const const_subiterator_type &it): 1575 container_const_reference<indirect_array> (ia), it_ (it) {} 1576 1577 // Arithmetic 1578 BOOST_UBLAS_INLINE 1579 const_iterator &operator ++ () { 1580 ++ it_; 1581 return *this; 1582 } 1583 BOOST_UBLAS_INLINE 1584 const_iterator &operator -- () { 1585 -- it_; 1586 return *this; 1587 } 1588 BOOST_UBLAS_INLINE 1589 const_iterator &operator += (difference_type n) { 1590 it_ += n; 1591 return *this; 1592 } 1593 BOOST_UBLAS_INLINE 1594 const_iterator &operator -= (difference_type n) { 1595 it_ -= n; 1596 return *this; 1597 } 1598 BOOST_UBLAS_INLINE 1599 difference_type operator - (const const_iterator &it) const { 1600 return it_ - it.it_; 1601 } 1602 1603 // Dereference 1604 BOOST_UBLAS_INLINE 1605 const_reference operator * () const { 1606 return (*this) () (it_); 1607 } 1608 1609 BOOST_UBLAS_INLINE 1610 const_reference operator [] (difference_type n) const { 1611 return *(*this + n); 1612 } 1613 1614 // Index 1615 BOOST_UBLAS_INLINE 1616 size_type index () const { 1617 return it_; 1618 } 1619 1620 // Assignment 1621 BOOST_UBLAS_INLINE 1622 const_iterator &operator = (const const_iterator &it) { 1623 // Comeau recommends... 1624 this->assign (&it ()); 1625 it_ = it.it_; 1626 return *this; 1627 } 1628 1629 // Comparison 1630 BOOST_UBLAS_INLINE 1631 bool operator == (const const_iterator &it) const { 1632 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 1633 return it_ == it.it_; 1634 } 1635 BOOST_UBLAS_INLINE 1636 bool operator < (const const_iterator &it) const { 1637 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 1638 return it_ < it.it_; 1639 } 1640 1641 private: 1642 const_subiterator_type it_; 1643 }; 1644 #endif 1645 1646 BOOST_UBLAS_INLINE begin() const1647 const_iterator begin () const { 1648 return const_iterator (*this, 0); 1649 } 1650 BOOST_UBLAS_INLINE cbegin() const1651 const_iterator cbegin () const { 1652 return begin (); 1653 } 1654 BOOST_UBLAS_INLINE end() const1655 const_iterator end () const { 1656 return const_iterator (*this, size_); 1657 } 1658 BOOST_UBLAS_INLINE cend() const1659 const_iterator cend () const { 1660 return end (); 1661 } 1662 1663 // Reverse iterator 1664 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 1665 1666 BOOST_UBLAS_INLINE rbegin() const1667 const_reverse_iterator rbegin () const { 1668 return const_reverse_iterator (end ()); 1669 } 1670 BOOST_UBLAS_INLINE crbegin() const1671 const_reverse_iterator crbegin () const { 1672 return rbegin (); 1673 } 1674 BOOST_UBLAS_INLINE rend() const1675 const_reverse_iterator rend () const { 1676 return const_reverse_iterator (begin ()); 1677 } 1678 BOOST_UBLAS_INLINE crend() const1679 const_reverse_iterator crend () const { 1680 return rend (); 1681 } 1682 1683 BOOST_UBLAS_INLINE preprocess(size_type size) const1684 indirect_array preprocess (size_type size) const { 1685 if (this != &all_) 1686 return *this; 1687 indirect_array ia (size); 1688 for (size_type i = 0; i < size; ++ i) 1689 ia (i) = i; 1690 return ia; 1691 } 1692 static 1693 BOOST_UBLAS_INLINE all()1694 const indirect_array &all () { 1695 return all_; 1696 } 1697 1698 private: 1699 size_type size_; 1700 array_type data_; 1701 static const indirect_array all_; 1702 }; 1703 1704 template<class A> 1705 const indirect_array<A> indirect_array<A>::all_; 1706 1707 1708 1709 // Gunter Winkler contributed the classes index_pair, index_pair_array, 1710 // index_triple and index_triple_array to enable inplace sort of parallel arrays. 1711 1712 template <class V> 1713 class index_pair : 1714 public container_reference<V> { 1715 1716 typedef index_pair<V> self_type; 1717 public: 1718 typedef typename V::size_type size_type; 1719 1720 BOOST_UBLAS_INLINE index_pair(V & v,size_type i)1721 index_pair(V& v, size_type i) : 1722 container_reference<V>(v), i_(i), 1723 v1_(v.data1_[i]), v2_(v.data2_[i]), 1724 dirty_(false), is_copy_(false) {} 1725 BOOST_UBLAS_INLINE index_pair(const self_type & rhs)1726 index_pair(const self_type& rhs) : 1727 container_reference<V>(rhs()), i_(0), 1728 v1_(rhs.v1_), v2_(rhs.v2_), 1729 dirty_(false), is_copy_(true) {} 1730 BOOST_UBLAS_INLINE ~index_pair()1731 ~index_pair() { 1732 if (dirty_ && (!is_copy_) ) { 1733 (*this)().data1_[i_] = v1_; 1734 (*this)().data2_[i_] = v2_; 1735 } 1736 } 1737 1738 BOOST_UBLAS_INLINE operator =(const self_type & rhs)1739 self_type& operator=(const self_type& rhs) { 1740 v1_ = rhs.v1_; 1741 v2_ = rhs.v2_; 1742 dirty_ = true; 1743 return *this; 1744 } 1745 1746 BOOST_UBLAS_INLINE swap(self_type & rhs)1747 void swap(self_type& rhs) { 1748 self_type tmp(rhs); 1749 rhs = *this; 1750 *this = tmp; 1751 } 1752 1753 BOOST_UBLAS_INLINE swap(self_type & lhs,self_type & rhs)1754 friend void swap(self_type& lhs, self_type& rhs) { 1755 lhs.swap(rhs); 1756 } 1757 swap(self_type lhs,self_type rhs)1758 friend void swap(self_type lhs, self_type rhs) { // For gcc 4.8 and c++11 1759 lhs.swap(rhs); 1760 } 1761 1762 1763 BOOST_UBLAS_INLINE equal(const self_type & rhs) const1764 bool equal(const self_type& rhs) const { 1765 return (v1_ == rhs.v1_); 1766 } 1767 BOOST_UBLAS_INLINE less(const self_type & rhs) const1768 bool less(const self_type& rhs) const { 1769 return (v1_ < rhs.v1_); 1770 } 1771 BOOST_UBLAS_INLINE operator ==(const self_type & lhs,const self_type & rhs)1772 friend bool operator == (const self_type& lhs, const self_type& rhs) { 1773 return lhs.equal(rhs); 1774 } 1775 BOOST_UBLAS_INLINE operator !=(const self_type & lhs,const self_type & rhs)1776 friend bool operator != (const self_type& lhs, const self_type& rhs) { 1777 return !lhs.equal(rhs); 1778 } 1779 BOOST_UBLAS_INLINE operator <(const self_type & lhs,const self_type & rhs)1780 friend bool operator < (const self_type& lhs, const self_type& rhs) { 1781 return lhs.less(rhs); 1782 } 1783 BOOST_UBLAS_INLINE operator >=(const self_type & lhs,const self_type & rhs)1784 friend bool operator >= (const self_type& lhs, const self_type& rhs) { 1785 return !lhs.less(rhs); 1786 } 1787 BOOST_UBLAS_INLINE operator >(const self_type & lhs,const self_type & rhs)1788 friend bool operator > (const self_type& lhs, const self_type& rhs) { 1789 return rhs.less(lhs); 1790 } 1791 BOOST_UBLAS_INLINE operator <=(const self_type & lhs,const self_type & rhs)1792 friend bool operator <= (const self_type& lhs, const self_type& rhs) { 1793 return !rhs.less(lhs); 1794 } 1795 1796 private: 1797 size_type i_; 1798 typename V::value1_type v1_; 1799 typename V::value2_type v2_; 1800 bool dirty_; 1801 bool is_copy_; 1802 }; 1803 1804 template <class V1, class V2> 1805 class index_pair_array: 1806 private boost::noncopyable { 1807 1808 typedef index_pair_array<V1, V2> self_type; 1809 public: 1810 typedef typename V1::value_type value1_type; 1811 typedef typename V2::value_type value2_type; 1812 1813 typedef typename V1::size_type size_type; 1814 typedef typename V1::difference_type difference_type; 1815 typedef index_pair<self_type> value_type; 1816 // There is nothing that can be referenced directly. Always return a copy of the index_pair 1817 typedef value_type reference; 1818 typedef const value_type const_reference; 1819 1820 BOOST_UBLAS_INLINE index_pair_array(size_type size,V1 & data1,V2 & data2)1821 index_pair_array(size_type size, V1& data1, V2& data2) : 1822 size_(size),data1_(data1),data2_(data2) {} 1823 1824 BOOST_UBLAS_INLINE size() const1825 size_type size() const { 1826 return size_; 1827 } 1828 1829 BOOST_UBLAS_INLINE operator ()(size_type i) const1830 const_reference operator () (size_type i) const { 1831 return value_type((*this), i); 1832 } 1833 BOOST_UBLAS_INLINE operator ()(size_type i)1834 reference operator () (size_type i) { 1835 return value_type((*this), i); 1836 } 1837 1838 typedef indexed_iterator<self_type, std::random_access_iterator_tag> iterator; 1839 typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator; 1840 1841 BOOST_UBLAS_INLINE begin()1842 iterator begin() { 1843 return iterator( (*this), 0); 1844 } 1845 BOOST_UBLAS_INLINE end()1846 iterator end() { 1847 return iterator( (*this), size()); 1848 } 1849 1850 BOOST_UBLAS_INLINE begin() const1851 const_iterator begin() const { 1852 return const_iterator( (*this), 0); 1853 } 1854 BOOST_UBLAS_INLINE cbegin() const1855 const_iterator cbegin () const { 1856 return begin (); 1857 } 1858 BOOST_UBLAS_INLINE end() const1859 const_iterator end() const { 1860 return const_iterator( (*this), size()); 1861 } 1862 BOOST_UBLAS_INLINE cend() const1863 const_iterator cend () const { 1864 return end (); 1865 } 1866 1867 // unnecessary function: 1868 BOOST_UBLAS_INLINE equal(size_type i1,size_type i2) const1869 bool equal(size_type i1, size_type i2) const { 1870 return data1_[i1] == data1_[i2]; 1871 } 1872 BOOST_UBLAS_INLINE less(size_type i1,size_type i2) const1873 bool less(size_type i1, size_type i2) const { 1874 return data1_[i1] < data1_[i2]; 1875 } 1876 1877 // gives a large speedup 1878 BOOST_UBLAS_INLINE iter_swap(const iterator & lhs,const iterator & rhs)1879 friend void iter_swap(const iterator& lhs, const iterator& rhs) { 1880 const size_type i1 = lhs.index(); 1881 const size_type i2 = rhs.index(); 1882 std::swap(lhs().data1_[i1], rhs().data1_[i2]); 1883 std::swap(lhs().data2_[i1], rhs().data2_[i2]); 1884 } 1885 1886 private: 1887 size_type size_; 1888 V1& data1_; 1889 V2& data2_; 1890 1891 // friend class value_type; 1892 friend class index_pair<self_type>; 1893 }; 1894 1895 template <class M> 1896 class index_triple : 1897 public container_reference<M> { 1898 1899 typedef index_triple<M> self_type; 1900 public: 1901 typedef typename M::size_type size_type; 1902 1903 BOOST_UBLAS_INLINE index_triple(M & m,size_type i)1904 index_triple(M& m, size_type i) : 1905 container_reference<M>(m), i_(i), 1906 v1_(m.data1_[i]), v2_(m.data2_[i]), v3_(m.data3_[i]), 1907 dirty_(false), is_copy_(false) {} 1908 BOOST_UBLAS_INLINE index_triple(const self_type & rhs)1909 index_triple(const self_type& rhs) : 1910 container_reference<M>(rhs()), i_(0), 1911 v1_(rhs.v1_), v2_(rhs.v2_), v3_(rhs.v3_), 1912 dirty_(false), is_copy_(true) {} 1913 BOOST_UBLAS_INLINE ~index_triple()1914 ~index_triple() { 1915 if (dirty_ && (!is_copy_) ) { 1916 (*this)().data1_[i_] = v1_; 1917 (*this)().data2_[i_] = v2_; 1918 (*this)().data3_[i_] = v3_; 1919 } 1920 } 1921 1922 BOOST_UBLAS_INLINE operator =(const self_type & rhs)1923 self_type& operator=(const self_type& rhs) { 1924 v1_ = rhs.v1_; 1925 v2_ = rhs.v2_; 1926 v3_ = rhs.v3_; 1927 dirty_ = true; 1928 return *this; 1929 } 1930 1931 BOOST_UBLAS_INLINE swap(self_type & rhs)1932 void swap(self_type& rhs) { 1933 self_type tmp(rhs); 1934 rhs = *this; 1935 *this = tmp; 1936 } 1937 1938 BOOST_UBLAS_INLINE swap(self_type & lhs,self_type & rhs)1939 friend void swap(self_type& lhs, self_type& rhs) { 1940 lhs.swap(rhs); 1941 } 1942 swap(self_type lhs,self_type rhs)1943 friend void swap(self_type lhs, self_type rhs) { // For gcc 4.8 and c++11 1944 lhs.swap(rhs); 1945 } 1946 1947 BOOST_UBLAS_INLINE equal(const self_type & rhs) const1948 bool equal(const self_type& rhs) const { 1949 return ((v1_ == rhs.v1_) && (v2_ == rhs.v2_)); 1950 } 1951 BOOST_UBLAS_INLINE less(const self_type & rhs) const1952 bool less(const self_type& rhs) const { 1953 return ((v1_ < rhs.v1_) || 1954 (v1_ == rhs.v1_ && v2_ < rhs.v2_)); 1955 } 1956 BOOST_UBLAS_INLINE operator ==(const self_type & lhs,const self_type & rhs)1957 friend bool operator == (const self_type& lhs, const self_type& rhs) { 1958 return lhs.equal(rhs); 1959 } 1960 BOOST_UBLAS_INLINE operator !=(const self_type & lhs,const self_type & rhs)1961 friend bool operator != (const self_type& lhs, const self_type& rhs) { 1962 return !lhs.equal(rhs); 1963 } 1964 BOOST_UBLAS_INLINE operator <(const self_type & lhs,const self_type & rhs)1965 friend bool operator < (const self_type& lhs, const self_type& rhs) { 1966 return lhs.less(rhs); 1967 } 1968 BOOST_UBLAS_INLINE operator >=(const self_type & lhs,const self_type & rhs)1969 friend bool operator >= (const self_type& lhs, const self_type& rhs) { 1970 return !lhs.less(rhs); 1971 } 1972 BOOST_UBLAS_INLINE operator >(const self_type & lhs,const self_type & rhs)1973 friend bool operator > (const self_type& lhs, const self_type& rhs) { 1974 return rhs.less(lhs); 1975 } 1976 BOOST_UBLAS_INLINE operator <=(const self_type & lhs,const self_type & rhs)1977 friend bool operator <= (const self_type& lhs, const self_type& rhs) { 1978 return !rhs.less(lhs); 1979 } 1980 1981 private: 1982 size_type i_; 1983 typename M::value1_type v1_; 1984 typename M::value2_type v2_; 1985 typename M::value3_type v3_; 1986 bool dirty_; 1987 bool is_copy_; 1988 }; 1989 1990 template <class V1, class V2, class V3> 1991 class index_triple_array: 1992 private boost::noncopyable { 1993 1994 typedef index_triple_array<V1, V2, V3> self_type; 1995 public: 1996 typedef typename V1::value_type value1_type; 1997 typedef typename V2::value_type value2_type; 1998 typedef typename V3::value_type value3_type; 1999 2000 typedef typename V1::size_type size_type; 2001 typedef typename V1::difference_type difference_type; 2002 typedef index_triple<self_type> value_type; 2003 // There is nothing that can be referenced directly. Always return a copy of the index_triple 2004 typedef value_type reference; 2005 typedef const value_type const_reference; 2006 2007 BOOST_UBLAS_INLINE index_triple_array(size_type size,V1 & data1,V2 & data2,V3 & data3)2008 index_triple_array(size_type size, V1& data1, V2& data2, V3& data3) : 2009 size_(size),data1_(data1),data2_(data2),data3_(data3) {} 2010 2011 BOOST_UBLAS_INLINE size() const2012 size_type size() const { 2013 return size_; 2014 } 2015 2016 BOOST_UBLAS_INLINE operator ()(size_type i) const2017 const_reference operator () (size_type i) const { 2018 return value_type((*this), i); 2019 } 2020 BOOST_UBLAS_INLINE operator ()(size_type i)2021 reference operator () (size_type i) { 2022 return value_type((*this), i); 2023 } 2024 2025 typedef indexed_iterator<self_type, std::random_access_iterator_tag> iterator; 2026 typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator; 2027 2028 BOOST_UBLAS_INLINE begin()2029 iterator begin() { 2030 return iterator( (*this), 0); 2031 } 2032 BOOST_UBLAS_INLINE end()2033 iterator end() { 2034 return iterator( (*this), size()); 2035 } 2036 2037 BOOST_UBLAS_INLINE begin() const2038 const_iterator begin() const { 2039 return const_iterator( (*this), 0); 2040 } 2041 BOOST_UBLAS_INLINE cbegin() const2042 const_iterator cbegin () const { 2043 return begin (); 2044 } 2045 BOOST_UBLAS_INLINE end() const2046 const_iterator end() const { 2047 return const_iterator( (*this), size()); 2048 } 2049 BOOST_UBLAS_INLINE cend() const2050 const_iterator cend () const { 2051 return end (); 2052 } 2053 2054 // unnecessary function: 2055 BOOST_UBLAS_INLINE equal(size_type i1,size_type i2) const2056 bool equal(size_type i1, size_type i2) const { 2057 return ((data1_[i1] == data1_[i2]) && (data2_[i1] == data2_[i2])); 2058 } 2059 BOOST_UBLAS_INLINE less(size_type i1,size_type i2) const2060 bool less(size_type i1, size_type i2) const { 2061 return ((data1_[i1] < data1_[i2]) || 2062 (data1_[i1] == data1_[i2] && data2_[i1] < data2_[i2])); 2063 } 2064 2065 // gives a large speedup 2066 BOOST_UBLAS_INLINE iter_swap(const iterator & lhs,const iterator & rhs)2067 friend void iter_swap(const iterator& lhs, const iterator& rhs) { 2068 const size_type i1 = lhs.index(); 2069 const size_type i2 = rhs.index(); 2070 std::swap(lhs().data1_[i1], rhs().data1_[i2]); 2071 std::swap(lhs().data2_[i1], rhs().data2_[i2]); 2072 std::swap(lhs().data3_[i1], rhs().data3_[i2]); 2073 } 2074 2075 private: 2076 size_type size_; 2077 V1& data1_; 2078 V2& data2_; 2079 V3& data3_; 2080 2081 // friend class value_type; 2082 friend class index_triple<self_type>; 2083 }; 2084 2085 }}} 2086 2087 #endif 2088