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/core/allocator_access.hpp> 22 #include <boost/serialization/array.hpp> 23 #include <boost/serialization/collection_size_type.hpp> 24 #include <boost/serialization/nvp.hpp> 25 26 #include <boost/numeric/ublas/exception.hpp> 27 #include <boost/numeric/ublas/traits.hpp> 28 #include <boost/numeric/ublas/detail/iterator.hpp> 29 30 31 namespace boost { namespace numeric { namespace ublas { 32 33 34 // Base class for Storage Arrays - see the Barton Nackman trick 35 template<class E> 36 class storage_array: 37 private nonassignable { 38 }; 39 40 41 // Unbounded array - with allocator 42 template<class T, class ALLOC> 43 class unbounded_array: 44 public storage_array<unbounded_array<T, ALLOC> > { 45 46 typedef unbounded_array<T, ALLOC> self_type; 47 public: 48 typedef ALLOC allocator_type; 49 typedef typename boost::allocator_size_type<ALLOC>::type size_type; 50 typedef typename boost::allocator_difference_type<ALLOC>::type difference_type; 51 typedef T value_type; 52 typedef const T &const_reference; 53 typedef T &reference; 54 typedef const T *const_pointer; 55 typedef T *pointer; 56 typedef const_pointer const_iterator; 57 typedef pointer iterator; 58 59 // Construction and destruction 60 explicit BOOST_UBLAS_INLINE unbounded_array(const ALLOC & a=ALLOC ())61 unbounded_array (const ALLOC &a = ALLOC()): 62 alloc_ (a), size_ (0) { 63 data_ = 0; 64 } 65 explicit BOOST_UBLAS_INLINE unbounded_array(size_type size,const ALLOC & a=ALLOC ())66 unbounded_array (size_type size, const ALLOC &a = ALLOC()): 67 alloc_(a), size_ (size) { 68 if (size_) { 69 data_ = alloc_.allocate (size_); 70 //Disabled warning C4127 because the conditional expression is constant 71 #ifdef _MSC_VER 72 #pragma warning(push) 73 #pragma warning(disable: 4127) 74 #endif 75 if (! detail::has_trivial_constructor<T>::value) { 76 #ifdef _MSC_VER 77 #pragma warning(pop) 78 #endif 79 for (pointer d = data_; d != data_ + size_; ++d) 80 boost::allocator_construct(alloc_, d); 81 } 82 } 83 else 84 data_ = 0; 85 } 86 // No value initialised, but still be default constructed 87 BOOST_UBLAS_INLINE unbounded_array(size_type size,const value_type & init,const ALLOC & a=ALLOC ())88 unbounded_array (size_type size, const value_type &init, const ALLOC &a = ALLOC()): 89 alloc_ (a), size_ (size) { 90 if (size_) { 91 data_ = alloc_.allocate (size_); 92 std::uninitialized_fill (begin(), end(), init); 93 } 94 else 95 data_ = 0; 96 } 97 BOOST_UBLAS_INLINE unbounded_array(const unbounded_array & c)98 unbounded_array (const unbounded_array &c): 99 storage_array<unbounded_array<T, ALLOC> >(), 100 alloc_ (c.alloc_), size_ (c.size_) { 101 if (size_) { 102 data_ = alloc_.allocate (size_); 103 std::uninitialized_copy (c.begin(), c.end(), begin()); 104 } 105 else 106 data_ = 0; 107 } 108 #ifdef BOOST_UBLAS_CPP_GE_2011 109 BOOST_UBLAS_INLINE unbounded_array(unbounded_array && c)110 unbounded_array (unbounded_array &&c) : 111 storage_array<unbounded_array<T, ALLOC> >(), 112 alloc_ (std::move(c.alloc_)), size_ (c.size_), data_(c.data_) 113 { 114 c.size_ = 0; 115 c.data_ = nullptr; 116 } 117 #endif 118 BOOST_UBLAS_INLINE ~unbounded_array()119 ~unbounded_array () { 120 if (size_) { 121 //Disabled warning C4127 because the conditional expression is constant 122 #ifdef _MSC_VER 123 #pragma warning(push) 124 #pragma warning(disable: 4127) 125 #endif 126 if (! detail::has_trivial_destructor<T>::value) { 127 #ifdef _MSC_VER 128 #pragma warning(pop) 129 #endif 130 // std::_Destroy (begin(), end(), alloc_); 131 const iterator i_end = end(); 132 for (iterator i = begin (); i != i_end; ++i) { 133 iterator_destroy (i); 134 } 135 } 136 alloc_.deallocate (data_, size_); 137 } 138 } 139 140 // Resizing 141 private: 142 BOOST_UBLAS_INLINE resize_internal(const size_type size,const value_type init,const bool preserve)143 void resize_internal (const size_type size, const value_type init, const bool preserve) { 144 if (size != size_) { 145 pointer p_data = data_; 146 if (size) { 147 data_ = alloc_.allocate (size); 148 if (preserve) { 149 pointer si = p_data; 150 pointer di = data_; 151 if (size < size_) { 152 for (; di != data_ + size; ++di) { 153 boost::allocator_construct(alloc_, di, *si); 154 ++si; 155 } 156 } 157 else { 158 for (; si != p_data + size_; ++si) { 159 boost::allocator_construct(alloc_, di, *si); 160 ++di; 161 } 162 for (; di != data_ + size; ++di) { 163 boost::allocator_construct(alloc_, di, init); 164 } 165 } 166 } 167 else { 168 //Disabled warning C4127 because the conditional expression is constant 169 #ifdef _MSC_VER 170 #pragma warning(push) 171 #pragma warning(disable: 4127) 172 #endif 173 if (! detail::has_trivial_constructor<T>::value) { 174 #ifdef _MSC_VER 175 #pragma warning(pop) 176 #endif 177 for (pointer di = data_; di != data_ + size; ++di) 178 boost::allocator_construct(alloc_, di); 179 } 180 } 181 } 182 183 if (size_) { 184 //Disabled warning C4127 because the conditional expression is constant 185 #ifdef _MSC_VER 186 #pragma warning(push) 187 #pragma warning(disable: 4127) 188 #endif 189 if (! detail::has_trivial_destructor<T>::value) { 190 #ifdef _MSC_VER 191 #pragma warning(pop) 192 #endif 193 for (pointer si = p_data; si != p_data + size_; ++si) 194 boost::allocator_destroy(alloc_, si); 195 } 196 alloc_.deallocate (p_data, size_); 197 } 198 199 if (!size) 200 data_ = 0; 201 size_ = size; 202 } 203 } 204 public: 205 BOOST_UBLAS_INLINE resize(size_type size)206 void resize (size_type size) { 207 resize_internal (size, value_type (), false); 208 } 209 BOOST_UBLAS_INLINE resize(size_type size,value_type init)210 void resize (size_type size, value_type init) { 211 resize_internal (size, init, true); 212 } 213 214 // Random Access Container 215 BOOST_UBLAS_INLINE max_size() const216 size_type max_size () const { 217 return boost::allocator_max_size(alloc_); 218 } 219 220 BOOST_UBLAS_INLINE empty() const221 bool empty () const { 222 return size_ == 0; 223 } 224 225 BOOST_UBLAS_INLINE size() const226 size_type size () const { 227 return size_; 228 } 229 230 // Element access 231 BOOST_UBLAS_INLINE operator [](size_type i) const232 const_reference operator [] (size_type i) const { 233 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 234 return data_ [i]; 235 } 236 BOOST_UBLAS_INLINE operator [](size_type i)237 reference operator [] (size_type i) { 238 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 239 return data_ [i]; 240 } 241 242 // Assignment 243 BOOST_UBLAS_INLINE operator =(const unbounded_array & a)244 unbounded_array &operator = (const unbounded_array &a) { 245 if (this != &a) { 246 resize (a.size_); 247 std::copy (a.data_, a.data_ + a.size_, data_); 248 } 249 return *this; 250 } 251 BOOST_UBLAS_INLINE assign_temporary(unbounded_array & a)252 unbounded_array &assign_temporary (unbounded_array &a) { 253 swap (a); 254 return *this; 255 } 256 257 // Swapping 258 BOOST_UBLAS_INLINE swap(unbounded_array & a)259 void swap (unbounded_array &a) { 260 if (this != &a) { 261 std::swap (size_, a.size_); 262 std::swap (data_, a.data_); 263 } 264 } 265 BOOST_UBLAS_INLINE swap(unbounded_array & a1,unbounded_array & a2)266 friend void swap (unbounded_array &a1, unbounded_array &a2) { 267 a1.swap (a2); 268 } 269 270 BOOST_UBLAS_INLINE begin() const271 const_iterator begin () const { 272 return data_; 273 } 274 BOOST_UBLAS_INLINE cbegin() const275 const_iterator cbegin () const { 276 return begin (); 277 } 278 BOOST_UBLAS_INLINE end() const279 const_iterator end () const { 280 return data_ + size_; 281 } 282 BOOST_UBLAS_INLINE cend() const283 const_iterator cend () const { 284 return end (); 285 } 286 287 BOOST_UBLAS_INLINE begin()288 iterator begin () { 289 return data_; 290 } 291 BOOST_UBLAS_INLINE end()292 iterator end () { 293 return data_ + size_; 294 } 295 296 // Reverse iterators 297 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 298 typedef std::reverse_iterator<iterator> reverse_iterator; 299 300 BOOST_UBLAS_INLINE rbegin() const301 const_reverse_iterator rbegin () const { 302 return const_reverse_iterator (end ()); 303 } 304 BOOST_UBLAS_INLINE crbegin() const305 const_reverse_iterator crbegin () const { 306 return rbegin (); 307 } 308 BOOST_UBLAS_INLINE rend() const309 const_reverse_iterator rend () const { 310 return const_reverse_iterator (begin ()); 311 } 312 BOOST_UBLAS_INLINE crend() const313 const_reverse_iterator crend () const { 314 return rend (); 315 } 316 BOOST_UBLAS_INLINE rbegin()317 reverse_iterator rbegin () { 318 return reverse_iterator (end ()); 319 } 320 BOOST_UBLAS_INLINE rend()321 reverse_iterator rend () { 322 return reverse_iterator (begin ()); 323 } 324 325 // Allocator get_allocator()326 allocator_type get_allocator () { 327 return alloc_; 328 } 329 330 private: 331 friend class boost::serialization::access; 332 333 // Serialization 334 template<class Archive> serialize(Archive & ar,const unsigned int)335 void serialize(Archive & ar, const unsigned int /*version*/) 336 { 337 serialization::collection_size_type s(size_); 338 ar & serialization::make_nvp("size",s); 339 if ( Archive::is_loading::value ) { 340 resize(s); 341 } 342 ar & serialization::make_array(data_, s); 343 } 344 345 private: 346 // Handle explict destroy on a (possibly indexed) iterator 347 BOOST_UBLAS_INLINE iterator_destroy(iterator & i)348 static void iterator_destroy (iterator &i) { 349 (void)(i); 350 (&(*i)) -> ~value_type (); 351 } 352 ALLOC alloc_; 353 size_type size_; 354 pointer data_; 355 }; 356 357 // Bounded array - with allocator for size_type and difference_type 358 template<class T, std::size_t N, class ALLOC> 359 class bounded_array: 360 public storage_array<bounded_array<T, N, ALLOC> > { 361 362 typedef bounded_array<T, N, ALLOC> self_type; 363 public: 364 // No allocator_type as ALLOC is not used for allocation 365 typedef typename boost::allocator_size_type<ALLOC>::type size_type; 366 typedef typename boost::allocator_difference_type<ALLOC>::type difference_type; 367 typedef T value_type; 368 typedef const T &const_reference; 369 typedef T &reference; 370 typedef const T *const_pointer; 371 typedef T *pointer; 372 typedef const_pointer const_iterator; 373 typedef pointer iterator; 374 375 // Construction and destruction 376 BOOST_UBLAS_INLINE bounded_array()377 bounded_array (): 378 size_ (0) /*, data_ ()*/ { // size 0 - use bounded_vector to default construct with size N 379 } 380 explicit BOOST_UBLAS_INLINE bounded_array(size_type size)381 bounded_array (size_type size): 382 size_ (size) /*, data_ ()*/ { 383 BOOST_UBLAS_CHECK (size_ <= N, bad_size ()); 384 // data_ (an array) elements are already default constructed 385 } 386 BOOST_UBLAS_INLINE bounded_array(size_type size,const value_type & init)387 bounded_array (size_type size, const value_type &init): 388 size_ (size) /*, data_ ()*/ { 389 BOOST_UBLAS_CHECK (size_ <= N, bad_size ()); 390 // ISSUE elements should be value constructed here, but we must fill instead as already default constructed 391 std::fill (begin(), end(), init) ; 392 } 393 BOOST_UBLAS_INLINE bounded_array(const bounded_array & c)394 bounded_array (const bounded_array &c): 395 size_ (c.size_) { 396 // ISSUE elements should be copy constructed here, but we must copy instead as already default constructed 397 std::copy (c.begin(), c.end(), begin()); 398 } 399 400 // Resizing 401 BOOST_UBLAS_INLINE resize(size_type size)402 void resize (size_type size) { 403 BOOST_UBLAS_CHECK (size <= N, bad_size ()); 404 size_ = size; 405 } 406 BOOST_UBLAS_INLINE resize(size_type size,value_type init)407 void resize (size_type size, value_type init) { 408 BOOST_UBLAS_CHECK (size <= N, bad_size ()); 409 if (size > size_) 410 std::fill (data_ + size_, data_ + size, init); 411 size_ = size; 412 } 413 414 // Random Access Container 415 BOOST_UBLAS_INLINE max_size() const416 size_type max_size () const { 417 return N; 418 } 419 420 BOOST_UBLAS_INLINE empty() const421 bool empty () const { 422 return size_ == 0; 423 } 424 425 BOOST_UBLAS_INLINE size() const426 size_type size () const { 427 return size_; 428 } 429 430 // Element access 431 BOOST_UBLAS_INLINE operator [](size_type i) const432 const_reference operator [] (size_type i) const { 433 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 434 return data_ [i]; 435 } 436 BOOST_UBLAS_INLINE operator [](size_type i)437 reference operator [] (size_type i) { 438 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 439 return data_ [i]; 440 } 441 442 // Assignment 443 BOOST_UBLAS_INLINE operator =(const bounded_array & a)444 bounded_array &operator = (const bounded_array &a) { 445 if (this != &a) { 446 resize (a.size_); 447 std::copy (a.data_, a.data_ + a.size_, data_); 448 } 449 return *this; 450 } 451 BOOST_UBLAS_INLINE assign_temporary(bounded_array & a)452 bounded_array &assign_temporary (bounded_array &a) { 453 *this = a; 454 return *this; 455 } 456 457 // Swapping 458 BOOST_UBLAS_INLINE swap(bounded_array & a)459 void swap (bounded_array &a) { 460 if (this != &a) { 461 std::swap (size_, a.size_); 462 std::swap_ranges (data_, data_ + (std::max) (size_, a.size_), a.data_); 463 } 464 } 465 BOOST_UBLAS_INLINE swap(bounded_array & a1,bounded_array & a2)466 friend void swap (bounded_array &a1, bounded_array &a2) { 467 a1.swap (a2); 468 } 469 470 BOOST_UBLAS_INLINE begin() const471 const_iterator begin () const { 472 return data_; 473 } 474 BOOST_UBLAS_INLINE cbegin() const475 const_iterator cbegin () const { 476 return begin (); 477 } 478 BOOST_UBLAS_INLINE end() const479 const_iterator end () const { 480 return data_ + size_; 481 } 482 BOOST_UBLAS_INLINE cend() const483 const_iterator cend () const { 484 return end (); 485 } 486 487 BOOST_UBLAS_INLINE begin()488 iterator begin () { 489 return data_; 490 } 491 BOOST_UBLAS_INLINE end()492 iterator end () { 493 return data_ + size_; 494 } 495 496 // Reverse iterators 497 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 498 typedef std::reverse_iterator<iterator> reverse_iterator; 499 500 BOOST_UBLAS_INLINE rbegin() const501 const_reverse_iterator rbegin () const { 502 return const_reverse_iterator (end ()); 503 } 504 BOOST_UBLAS_INLINE crbegin() const505 const_reverse_iterator crbegin () const { 506 return rbegin (); 507 } 508 BOOST_UBLAS_INLINE rend() const509 const_reverse_iterator rend () const { 510 return const_reverse_iterator (begin ()); 511 } 512 BOOST_UBLAS_INLINE crend() const513 const_reverse_iterator crend () const { 514 return rend (); 515 } 516 BOOST_UBLAS_INLINE rbegin()517 reverse_iterator rbegin () { 518 return reverse_iterator (end ()); 519 } 520 BOOST_UBLAS_INLINE rend()521 reverse_iterator rend () { 522 return reverse_iterator (begin ()); 523 } 524 525 private: 526 // Serialization 527 friend class boost::serialization::access; 528 529 template<class Archive> serialize(Archive & ar,const unsigned int)530 void serialize(Archive & ar, const unsigned int /*version*/) 531 { 532 serialization::collection_size_type s(size_); 533 ar & serialization::make_nvp("size", s); 534 if ( Archive::is_loading::value ) { 535 if (s > N) bad_size("too large size in bounded_array::load()\n").raise(); 536 resize(s); 537 } 538 ar & serialization::make_array(data_, s); 539 } 540 541 private: 542 size_type size_; 543 // MSVC does not like arrays of size 0 in base classes. Hence, this conditionally changes the size to 1 544 #ifdef _MSC_VER 545 BOOST_UBLAS_BOUNDED_ARRAY_ALIGN value_type data_ [(N>0)?N:1]; 546 #else 547 BOOST_UBLAS_BOUNDED_ARRAY_ALIGN value_type data_ [N]; 548 #endif 549 }; 550 551 552 // Array adaptor with normal deep copy semantics of elements 553 template<class T> 554 class array_adaptor: 555 public storage_array<array_adaptor<T> > { 556 557 typedef array_adaptor<T> self_type; 558 public: 559 typedef std::size_t size_type; 560 typedef std::ptrdiff_t difference_type; 561 typedef T value_type; 562 typedef const T &const_reference; 563 typedef T &reference; 564 typedef const T *const_pointer; 565 typedef T *pointer; 566 567 // Construction and destruction 568 BOOST_UBLAS_INLINE array_adaptor()569 array_adaptor (): 570 size_ (0), own_ (true), data_ (new value_type [0]) { 571 } 572 explicit BOOST_UBLAS_INLINE array_adaptor(size_type size)573 array_adaptor (size_type size): 574 size_ (size), own_ (true), data_ (new value_type [size]) { 575 } 576 BOOST_UBLAS_INLINE array_adaptor(size_type size,const value_type & init)577 array_adaptor (size_type size, const value_type &init): 578 size_ (size), own_ (true), data_ (new value_type [size]) { 579 std::fill (data_, data_ + size_, init); 580 } 581 BOOST_UBLAS_INLINE array_adaptor(size_type size,pointer data)582 array_adaptor (size_type size, pointer data): 583 size_ (size), own_ (false), data_ (data) {} 584 585 template <size_t N> array_adaptor(T (& data)[N])586 BOOST_UBLAS_INLINE array_adaptor (T (&data)[N]): 587 size_ (N), own_ (false), data_ (data) {} 588 BOOST_UBLAS_INLINE array_adaptor(const array_adaptor & a)589 array_adaptor (const array_adaptor &a): 590 storage_array<self_type> (), 591 size_ (a.size_), own_ (true), data_ (new value_type [a.size_]) { 592 *this = a; 593 } 594 BOOST_UBLAS_INLINE ~array_adaptor()595 ~array_adaptor () { 596 if (own_) { 597 delete [] data_; 598 } 599 } 600 601 // Resizing 602 private: 603 BOOST_UBLAS_INLINE resize_internal(size_type size,value_type init,bool preserve=true)604 void resize_internal (size_type size, value_type init, bool preserve = true) { 605 if (size != size_) { 606 pointer data = new value_type [size]; 607 if (preserve) { 608 std::copy (data_, data_ + (std::min) (size, size_), data); 609 std::fill (data + (std::min) (size, size_), data + size, init); 610 } 611 if (own_) 612 delete [] data_; 613 size_ = size; 614 own_ = true; 615 data_ = data; 616 } 617 } 618 BOOST_UBLAS_INLINE resize_internal(size_type size,pointer data,value_type init,bool preserve=true)619 void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) { 620 if (data != data_) { 621 if (preserve) { 622 std::copy (data_, data_ + (std::min) (size, size_), data); 623 std::fill (data + (std::min) (size, size_), data + size, init); 624 } 625 if (own_) 626 delete [] data_; 627 own_ = false; 628 data_ = data; 629 } 630 else { 631 std::fill (data + (std::min) (size, size_), data + size, init); 632 } 633 size_ = size; 634 } 635 public: 636 BOOST_UBLAS_INLINE resize(size_type size)637 void resize (size_type size) { 638 resize_internal (size, value_type (), false); 639 } 640 BOOST_UBLAS_INLINE resize(size_type size,value_type init)641 void resize (size_type size, value_type init) { 642 resize_internal (size, init, true); 643 } 644 BOOST_UBLAS_INLINE resize(size_type size,pointer data)645 void resize (size_type size, pointer data) { 646 resize_internal (size, data, value_type (), false); 647 } 648 BOOST_UBLAS_INLINE resize(size_type size,pointer data,value_type init)649 void resize (size_type size, pointer data, value_type init) { 650 resize_internal (size, data, init, true); 651 } 652 653 template <size_t N> resize(T (& data)[N])654 BOOST_UBLAS_INLINE void resize (T (&data)[N]) { 655 resize_internal (N, data, value_type (), false); 656 } 657 658 template <size_t N> resize(T (& data)[N],value_type init)659 BOOST_UBLAS_INLINE void resize (T (&data)[N], value_type init) { 660 resize_internal (N, data, init, true); 661 } 662 663 BOOST_UBLAS_INLINE size() const664 size_type size () const { 665 return size_; 666 } 667 668 // Element access 669 BOOST_UBLAS_INLINE operator [](size_type i) const670 const_reference operator [] (size_type i) const { 671 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 672 return data_ [i]; 673 } 674 BOOST_UBLAS_INLINE operator [](size_type i)675 reference operator [] (size_type i) { 676 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 677 return data_ [i]; 678 } 679 680 // Assignment 681 BOOST_UBLAS_INLINE operator =(const array_adaptor & a)682 array_adaptor &operator = (const array_adaptor &a) { 683 if (this != &a) { 684 resize (a.size_); 685 std::copy (a.data_, a.data_ + a.size_, data_); 686 } 687 return *this; 688 } 689 BOOST_UBLAS_INLINE assign_temporary(array_adaptor & a)690 array_adaptor &assign_temporary (array_adaptor &a) { 691 if (own_ && a.own_) 692 swap (a); 693 else 694 *this = a; 695 return *this; 696 } 697 698 // Swapping 699 BOOST_UBLAS_INLINE swap(array_adaptor & a)700 void swap (array_adaptor &a) { 701 if (this != &a) { 702 std::swap (size_, a.size_); 703 std::swap (own_, a.own_); 704 std::swap (data_, a.data_); 705 } 706 } 707 BOOST_UBLAS_INLINE swap(array_adaptor & a1,array_adaptor & a2)708 friend void swap (array_adaptor &a1, array_adaptor &a2) { 709 a1.swap (a2); 710 } 711 712 // Iterators simply are pointers. 713 714 typedef const_pointer const_iterator; 715 716 BOOST_UBLAS_INLINE begin() const717 const_iterator begin () const { 718 return data_; 719 } 720 BOOST_UBLAS_INLINE cbegin() const721 const_iterator cbegin () const { 722 return begin (); 723 } 724 BOOST_UBLAS_INLINE end() const725 const_iterator end () const { 726 return data_ + size_; 727 } 728 BOOST_UBLAS_INLINE cend() const729 const_iterator cend () const { 730 return end (); 731 } 732 733 typedef pointer iterator; 734 735 BOOST_UBLAS_INLINE begin()736 iterator begin () { 737 return data_; 738 } 739 BOOST_UBLAS_INLINE end()740 iterator end () { 741 return data_ + size_; 742 } 743 744 // Reverse iterators 745 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 746 typedef std::reverse_iterator<iterator> reverse_iterator; 747 748 BOOST_UBLAS_INLINE rbegin() const749 const_reverse_iterator rbegin () const { 750 return const_reverse_iterator (end ()); 751 } 752 BOOST_UBLAS_INLINE crbegin() const753 const_reverse_iterator crbegin () const { 754 return rbegin (); 755 } 756 BOOST_UBLAS_INLINE rend() const757 const_reverse_iterator rend () const { 758 return const_reverse_iterator (begin ()); 759 } 760 BOOST_UBLAS_INLINE crend() const761 const_reverse_iterator crend () const { 762 return rend (); 763 } 764 BOOST_UBLAS_INLINE rbegin()765 reverse_iterator rbegin () { 766 return reverse_iterator (end ()); 767 } 768 BOOST_UBLAS_INLINE rend()769 reverse_iterator rend () { 770 return reverse_iterator (begin ()); 771 } 772 773 private: 774 size_type size_; 775 bool own_; 776 pointer data_; 777 }; 778 779 #ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR 780 // Array adaptor with shallow (reference) copy semantics of elements. 781 // shared_array is used to maintain reference counts. 782 // This class breaks the normal copy semantics for a storage container and is very dangerous! 783 template<class T> 784 class shallow_array_adaptor: 785 public storage_array<shallow_array_adaptor<T> > { 786 787 typedef shallow_array_adaptor<T> self_type; 788 789 template<class TT> 790 struct leaker { 791 typedef void result_type; 792 typedef TT *argument_type; 793 794 BOOST_UBLAS_INLINE operator ()boost::numeric::ublas::shallow_array_adaptor::leaker795 result_type operator () (argument_type /* x */) {} 796 }; 797 798 public: 799 typedef std::size_t size_type; 800 typedef std::ptrdiff_t difference_type; 801 typedef T value_type; 802 typedef const T &const_reference; 803 typedef T &reference; 804 typedef const T *const_pointer; 805 typedef T *pointer; 806 807 // Construction and destruction 808 BOOST_UBLAS_INLINE shallow_array_adaptor()809 shallow_array_adaptor (): 810 size_ (0), own_ (true), data_ (new value_type [0]) { 811 } 812 explicit BOOST_UBLAS_INLINE shallow_array_adaptor(size_type size)813 shallow_array_adaptor (size_type size): 814 size_ (size), own_ (true), data_ (new value_type [size]) { 815 } 816 BOOST_UBLAS_INLINE shallow_array_adaptor(size_type size,const value_type & init)817 shallow_array_adaptor (size_type size, const value_type &init): 818 size_ (size), own_ (true), data_ (new value_type [size]) { 819 std::fill (data_.get (), data_.get () + size_, init); 820 } 821 BOOST_UBLAS_INLINE shallow_array_adaptor(size_type size,pointer data)822 shallow_array_adaptor (size_type size, pointer data): 823 size_ (size), own_ (false), data_ (data, leaker<value_type> ()) {} 824 template <size_t N> 825 BOOST_UBLAS_INLINE shallow_array_adaptor(T (& data)[N])826 shallow_array_adaptor (T (&data)[N]): 827 size_ (N), own_ (false), data_ (data, leaker<value_type> ()) {} 828 829 BOOST_UBLAS_INLINE shallow_array_adaptor(const shallow_array_adaptor & a)830 shallow_array_adaptor (const shallow_array_adaptor &a): 831 storage_array<self_type> (), 832 size_ (a.size_), own_ (a.own_), data_ (a.data_) {} 833 834 BOOST_UBLAS_INLINE ~shallow_array_adaptor()835 ~shallow_array_adaptor () { 836 } 837 838 // Resizing 839 private: 840 BOOST_UBLAS_INLINE resize_internal(size_type size,value_type init,bool preserve=true)841 void resize_internal (size_type size, value_type init, bool preserve = true) { 842 if (size != size_) { 843 shared_array<value_type> data (new value_type [size]); 844 if (preserve) { 845 std::copy (data_.get (), data_.get () + (std::min) (size, size_), data.get ()); 846 std::fill (data.get () + (std::min) (size, size_), data.get () + size, init); 847 } 848 size_ = size; 849 own_ = true; 850 data_ = data; 851 } 852 } 853 BOOST_UBLAS_INLINE resize_internal(size_type size,pointer data,value_type init,bool preserve=true)854 void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) { 855 if (preserve) { 856 std::copy (data_.get (), data_.get () + (std::min) (size, size_), data); 857 std::fill (data + (std::min) (size, size_), data + size, init); 858 } 859 size_ = size; 860 own_ = false; 861 data_.reset(data, leaker<value_type> ()); 862 } 863 public: 864 BOOST_UBLAS_INLINE resize(size_type size)865 void resize (size_type size) { 866 resize_internal (size, value_type (), false); 867 } 868 BOOST_UBLAS_INLINE resize(size_type size,value_type init)869 void resize (size_type size, value_type init) { 870 resize_internal (size, init, true); 871 } 872 BOOST_UBLAS_INLINE resize(size_type size,pointer data)873 void resize (size_type size, pointer data) { 874 resize_internal (size, data, value_type (), false); 875 } 876 BOOST_UBLAS_INLINE resize(size_type size,pointer data,value_type init)877 void resize (size_type size, pointer data, value_type init) { 878 resize_internal (size, data, init, true); 879 } 880 template <size_t N> 881 BOOST_UBLAS_INLINE resize(T (& data)[N])882 void resize (T (&data)[N]) { 883 resize_internal (N, data, value_type (), false); 884 } 885 template <size_t N> 886 BOOST_UBLAS_INLINE resize(T (& data)[N],value_type init)887 void resize (T (&data)[N], value_type init) { 888 resize_internal (N, data, init, true); 889 } 890 891 BOOST_UBLAS_INLINE size() const892 size_type size () const { 893 return size_; 894 } 895 896 // Element access 897 BOOST_UBLAS_INLINE operator [](size_type i) const898 const_reference operator [] (size_type i) const { 899 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 900 return data_ [i]; 901 } 902 BOOST_UBLAS_INLINE operator [](size_type i)903 reference operator [] (size_type i) { 904 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 905 return data_ [i]; 906 } 907 908 // Assignment 909 BOOST_UBLAS_INLINE operator =(const shallow_array_adaptor & a)910 shallow_array_adaptor &operator = (const shallow_array_adaptor &a) { 911 if (this != &a) { 912 resize (a.size_); 913 std::copy (a.data_.get (), a.data_.get () + a.size_, data_.get ()); 914 } 915 return *this; 916 } 917 BOOST_UBLAS_INLINE assign_temporary(shallow_array_adaptor & a)918 shallow_array_adaptor &assign_temporary (shallow_array_adaptor &a) { 919 if (own_ && a.own_) 920 swap (a); 921 else 922 *this = a; 923 return *this; 924 } 925 926 // Swapping 927 BOOST_UBLAS_INLINE swap(shallow_array_adaptor & a)928 void swap (shallow_array_adaptor &a) { 929 if (this != &a) { 930 std::swap (size_, a.size_); 931 std::swap (own_, a.own_); 932 std::swap (data_, a.data_); 933 } 934 } 935 BOOST_UBLAS_INLINE swap(shallow_array_adaptor & a1,shallow_array_adaptor & a2)936 friend void swap (shallow_array_adaptor &a1, shallow_array_adaptor &a2) { 937 a1.swap (a2); 938 } 939 940 // Iterators simply are pointers. 941 942 typedef const_pointer const_iterator; 943 944 BOOST_UBLAS_INLINE begin() const945 const_iterator begin () const { 946 return data_.get (); 947 } 948 BOOST_UBLAS_INLINE cbegin() const949 const_iterator cbegin () const { 950 return begin (); 951 } 952 BOOST_UBLAS_INLINE end() const953 const_iterator end () const { 954 return data_.get () + size_; 955 } 956 BOOST_UBLAS_INLINE cend() const957 const_iterator cend () const { 958 return end (); 959 } 960 961 typedef pointer iterator; 962 963 BOOST_UBLAS_INLINE begin()964 iterator begin () { 965 return data_.get (); 966 } 967 BOOST_UBLAS_INLINE end()968 iterator end () { 969 return data_.get () + size_; 970 } 971 972 // Reverse iterators 973 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 974 typedef std::reverse_iterator<iterator> reverse_iterator; 975 976 BOOST_UBLAS_INLINE rbegin() const977 const_reverse_iterator rbegin () const { 978 return const_reverse_iterator (end ()); 979 } 980 BOOST_UBLAS_INLINE crbegin() const981 const_reverse_iterator crbegin () const { 982 return rbegin (); 983 } 984 BOOST_UBLAS_INLINE rend() const985 const_reverse_iterator rend () const { 986 return const_reverse_iterator (begin ()); 987 } 988 BOOST_UBLAS_INLINE crend() const989 const_reverse_iterator crend () const { 990 return rend (); 991 } 992 BOOST_UBLAS_INLINE rbegin()993 reverse_iterator rbegin () { 994 return reverse_iterator (end ()); 995 } 996 BOOST_UBLAS_INLINE rend()997 reverse_iterator rend () { 998 return reverse_iterator (begin ()); 999 } 1000 1001 private: 1002 size_type size_; 1003 bool own_; 1004 shared_array<value_type> data_; 1005 }; 1006 1007 #endif 1008 1009 1010 // Range class 1011 template <class Z, class D> 1012 class basic_range { 1013 typedef basic_range<Z, D> self_type; 1014 public: 1015 typedef Z size_type; 1016 typedef D difference_type; 1017 typedef size_type value_type; 1018 typedef value_type const_reference; 1019 typedef const_reference reference; 1020 typedef const value_type *const_pointer; 1021 typedef value_type *pointer; 1022 1023 // Construction and destruction 1024 BOOST_UBLAS_INLINE basic_range()1025 basic_range (): 1026 start_ (0), size_ (0) {} 1027 BOOST_UBLAS_INLINE basic_range(size_type start,size_type stop)1028 basic_range (size_type start, size_type stop): 1029 start_ (start), size_ (stop - start) { 1030 BOOST_UBLAS_CHECK (start_ <= stop, bad_index ()); 1031 } 1032 1033 BOOST_UBLAS_INLINE start() const1034 size_type start () const { 1035 return start_; 1036 } 1037 BOOST_UBLAS_INLINE size() const1038 size_type size () const { 1039 return size_; 1040 } 1041 1042 // Random Access Container 1043 BOOST_UBLAS_INLINE max_size() const1044 size_type max_size () const { 1045 return size_; 1046 } 1047 1048 BOOST_UBLAS_INLINE empty() const1049 bool empty () const { 1050 return size_ == 0; 1051 } 1052 1053 // Element access 1054 BOOST_UBLAS_INLINE operator ()(size_type i) const1055 const_reference operator () (size_type i) const { 1056 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 1057 return start_ + i; 1058 } 1059 1060 // Composition 1061 BOOST_UBLAS_INLINE compose(const basic_range & r) const1062 basic_range compose (const basic_range &r) const { 1063 return basic_range (start_ + r.start_, start_ + r.start_ + r.size_); 1064 } 1065 1066 // Comparison 1067 BOOST_UBLAS_INLINE operator ==(const basic_range & r) const1068 bool operator == (const basic_range &r) const { 1069 return start_ == r.start_ && size_ == r.size_; 1070 } 1071 BOOST_UBLAS_INLINE operator !=(const basic_range & r) const1072 bool operator != (const basic_range &r) const { 1073 return ! (*this == r); 1074 } 1075 1076 // Iterator types 1077 private: 1078 // Use and index 1079 typedef size_type const_subiterator_type; 1080 1081 public: 1082 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1083 typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator; 1084 #else 1085 class const_iterator: 1086 public container_const_reference<basic_range>, 1087 public random_access_iterator_base<std::random_access_iterator_tag, 1088 const_iterator, value_type> { 1089 public: 1090 typedef typename basic_range::value_type value_type; 1091 typedef typename basic_range::difference_type difference_type; 1092 typedef typename basic_range::const_reference reference; 1093 typedef typename basic_range::const_pointer pointer; 1094 1095 // Construction and destruction 1096 BOOST_UBLAS_INLINE 1097 const_iterator (): 1098 container_const_reference<basic_range> (), it_ () {} 1099 BOOST_UBLAS_INLINE 1100 const_iterator (const basic_range &r, const const_subiterator_type &it): 1101 container_const_reference<basic_range> (r), it_ (it) {} 1102 1103 // Arithmetic 1104 BOOST_UBLAS_INLINE 1105 const_iterator &operator ++ () { 1106 ++ it_; 1107 return *this; 1108 } 1109 BOOST_UBLAS_INLINE 1110 const_iterator &operator -- () { 1111 BOOST_UBLAS_CHECK (it_ > 0, bad_index ()); 1112 -- it_; 1113 return *this; 1114 } 1115 BOOST_UBLAS_INLINE 1116 const_iterator &operator += (difference_type n) { 1117 BOOST_UBLAS_CHECK (n >= 0 || it_ >= size_type(-n), bad_index ()); 1118 it_ += n; 1119 return *this; 1120 } 1121 BOOST_UBLAS_INLINE 1122 const_iterator &operator -= (difference_type n) { 1123 BOOST_UBLAS_CHECK (n <= 0 || it_ >= size_type(n), bad_index ()); 1124 it_ -= n; 1125 return *this; 1126 } 1127 BOOST_UBLAS_INLINE 1128 difference_type operator - (const const_iterator &it) const { 1129 return it_ - it.it_; 1130 } 1131 1132 // Dereference 1133 BOOST_UBLAS_INLINE 1134 const_reference operator * () const { 1135 BOOST_UBLAS_CHECK ((*this) ().start () <= it_, bad_index ()); 1136 BOOST_UBLAS_CHECK (it_ < (*this) ().start () + (*this) ().size (), bad_index ()); 1137 return it_; 1138 } 1139 1140 BOOST_UBLAS_INLINE 1141 const_reference operator [] (difference_type n) const { 1142 return *(*this + n); 1143 } 1144 1145 // Index 1146 BOOST_UBLAS_INLINE 1147 size_type index () const { 1148 BOOST_UBLAS_CHECK ((*this) ().start () <= it_, bad_index ()); 1149 BOOST_UBLAS_CHECK (it_ < (*this) ().start () + (*this) ().size (), bad_index ()); 1150 return it_ - (*this) ().start (); 1151 } 1152 1153 // Assignment 1154 BOOST_UBLAS_INLINE 1155 const_iterator &operator = (const const_iterator &it) { 1156 // Comeau recommends... 1157 this->assign (&it ()); 1158 it_ = it.it_; 1159 return *this; 1160 } 1161 1162 // Comparison 1163 BOOST_UBLAS_INLINE 1164 bool operator == (const const_iterator &it) const { 1165 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 1166 return it_ == it.it_; 1167 } 1168 BOOST_UBLAS_INLINE 1169 bool operator < (const const_iterator &it) const { 1170 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 1171 return it_ < it.it_; 1172 } 1173 1174 private: 1175 const_subiterator_type it_; 1176 }; 1177 #endif 1178 1179 BOOST_UBLAS_INLINE begin() const1180 const_iterator begin () const { 1181 return const_iterator (*this, start_); 1182 } 1183 BOOST_UBLAS_INLINE cbegin() const1184 const_iterator cbegin () const { 1185 return begin (); 1186 } 1187 BOOST_UBLAS_INLINE end() const1188 const_iterator end () const { 1189 return const_iterator (*this, start_ + size_); 1190 } 1191 BOOST_UBLAS_INLINE cend() const1192 const_iterator cend () const { 1193 return end (); 1194 } 1195 1196 // Reverse iterator 1197 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 1198 1199 BOOST_UBLAS_INLINE rbegin() const1200 const_reverse_iterator rbegin () const { 1201 return const_reverse_iterator (end ()); 1202 } 1203 BOOST_UBLAS_INLINE crbegin() const1204 const_reverse_iterator crbegin () const { 1205 return rbegin (); 1206 } 1207 BOOST_UBLAS_INLINE rend() const1208 const_reverse_iterator rend () const { 1209 return const_reverse_iterator (begin ()); 1210 } 1211 BOOST_UBLAS_INLINE crend() const1212 const_reverse_iterator crend () const { 1213 return rend (); 1214 } 1215 1216 BOOST_UBLAS_INLINE preprocess(size_type size) const1217 basic_range preprocess (size_type size) const { 1218 if (this != &all_) 1219 return *this; 1220 return basic_range (0, size); 1221 } 1222 static 1223 BOOST_UBLAS_INLINE all()1224 const basic_range &all () { 1225 return all_; 1226 } 1227 1228 private: 1229 size_type start_; 1230 size_type size_; 1231 static const basic_range all_; 1232 }; 1233 1234 template <class Z, class D> 1235 const basic_range<Z,D> basic_range<Z,D>::all_ (0, size_type (-1)); 1236 1237 1238 // Slice class 1239 template <class Z, class D> 1240 class basic_slice { 1241 typedef basic_slice<Z, D> self_type; 1242 public: 1243 typedef Z size_type; 1244 typedef D difference_type; 1245 typedef size_type value_type; 1246 typedef value_type const_reference; 1247 typedef const_reference reference; 1248 typedef const value_type *const_pointer; 1249 typedef value_type *pointer; 1250 1251 // Construction and destruction 1252 BOOST_UBLAS_INLINE basic_slice()1253 basic_slice (): 1254 start_ (0), stride_ (0), size_ (0) {} 1255 BOOST_UBLAS_INLINE basic_slice(size_type start,difference_type stride,size_type size)1256 basic_slice (size_type start, difference_type stride, size_type size): 1257 start_ (start), stride_ (stride), size_ (size) {} 1258 1259 BOOST_UBLAS_INLINE start() const1260 size_type start () const { 1261 return start_; 1262 } 1263 BOOST_UBLAS_INLINE stride() const1264 difference_type stride () const { 1265 return stride_; 1266 } 1267 BOOST_UBLAS_INLINE size() const1268 size_type size () const { 1269 return size_; 1270 } 1271 1272 // Random Access Container 1273 BOOST_UBLAS_INLINE max_size() const1274 size_type max_size () const { 1275 return size_; 1276 } 1277 1278 BOOST_UBLAS_INLINE empty() const1279 bool empty () const { 1280 return size_ == 0; 1281 } 1282 1283 // Element access 1284 BOOST_UBLAS_INLINE operator ()(size_type i) const1285 const_reference operator () (size_type i) const { 1286 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 1287 BOOST_UBLAS_CHECK (stride_ >= 0 || start_ >= i * -stride_, bad_index ()); 1288 return start_ + i * stride_; 1289 } 1290 1291 // Composition 1292 BOOST_UBLAS_INLINE compose(const basic_range<size_type,difference_type> & r) const1293 basic_slice compose (const basic_range<size_type, difference_type> &r) const { 1294 BOOST_UBLAS_CHECK (stride_ >=0 || start_ >= -stride_ * r.start(), bad_index ()); 1295 return basic_slice (start_ + stride_ * r.start (), stride_, r.size ()); 1296 } 1297 BOOST_UBLAS_INLINE compose(const basic_slice & s) const1298 basic_slice compose (const basic_slice &s) const { 1299 BOOST_UBLAS_CHECK (stride_ >=0 || start_ >= -stride_ * s.start_, bad_index ()); 1300 return basic_slice (start_ + stride_ * s.start_, stride_ * s.stride_, s.size_); 1301 } 1302 1303 // Comparison 1304 BOOST_UBLAS_INLINE operator ==(const basic_slice & s) const1305 bool operator == (const basic_slice &s) const { 1306 return start_ == s.start_ && stride_ == s.stride_ && size_ == s.size_; 1307 } 1308 BOOST_UBLAS_INLINE operator !=(const basic_slice & s) const1309 bool operator != (const basic_slice &s) const { 1310 return ! (*this == s); 1311 } 1312 1313 // Iterator types 1314 private: 1315 // Use and index 1316 typedef size_type const_subiterator_type; 1317 1318 public: 1319 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1320 typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator; 1321 #else 1322 class const_iterator: 1323 public container_const_reference<basic_slice>, 1324 public random_access_iterator_base<std::random_access_iterator_tag, 1325 const_iterator, value_type> { 1326 public: 1327 typedef typename basic_slice::value_type value_type; 1328 typedef typename basic_slice::difference_type difference_type; 1329 typedef typename basic_slice::const_reference reference; 1330 typedef typename basic_slice::const_pointer pointer; 1331 1332 // Construction and destruction 1333 BOOST_UBLAS_INLINE 1334 const_iterator (): 1335 container_const_reference<basic_slice> (), it_ () {} 1336 BOOST_UBLAS_INLINE 1337 const_iterator (const basic_slice &s, const const_subiterator_type &it): 1338 container_const_reference<basic_slice> (s), it_ (it) {} 1339 1340 // Arithmetic 1341 BOOST_UBLAS_INLINE 1342 const_iterator &operator ++ () { 1343 ++it_; 1344 return *this; 1345 } 1346 BOOST_UBLAS_INLINE 1347 const_iterator &operator -- () { 1348 BOOST_UBLAS_CHECK (it_ > 0, bad_index ()); 1349 --it_; 1350 return *this; 1351 } 1352 BOOST_UBLAS_INLINE 1353 const_iterator &operator += (difference_type n) { 1354 BOOST_UBLAS_CHECK (n >= 0 || it_ >= size_type(-n), bad_index ()); 1355 it_ += n; 1356 return *this; 1357 } 1358 BOOST_UBLAS_INLINE 1359 const_iterator &operator -= (difference_type n) { 1360 BOOST_UBLAS_CHECK (n <= 0 || it_ >= size_type(n), bad_index ()); 1361 it_ -= n; 1362 return *this; 1363 } 1364 BOOST_UBLAS_INLINE 1365 difference_type operator - (const const_iterator &it) const { 1366 return it_ - it.it_; 1367 } 1368 1369 // Dereference 1370 BOOST_UBLAS_INLINE 1371 const_reference operator * () const { 1372 BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ()); 1373 return (*this) ().start () + it_* (*this) ().stride (); 1374 } 1375 1376 BOOST_UBLAS_INLINE 1377 const_reference operator [] (difference_type n) const { 1378 return *(*this + n); 1379 } 1380 1381 // Index 1382 BOOST_UBLAS_INLINE 1383 size_type index () const { 1384 BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ()); 1385 return it_; 1386 } 1387 1388 // Assignment 1389 BOOST_UBLAS_INLINE 1390 const_iterator &operator = (const const_iterator &it) { 1391 // Comeau recommends... 1392 this->assign (&it ()); 1393 it_ = it.it_; 1394 return *this; 1395 } 1396 1397 // Comparison 1398 BOOST_UBLAS_INLINE 1399 bool operator == (const const_iterator &it) const { 1400 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 1401 return it_ == it.it_; 1402 } 1403 BOOST_UBLAS_INLINE 1404 bool operator < (const const_iterator &it) const { 1405 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 1406 return it_ < it.it_; 1407 } 1408 1409 private: 1410 const_subiterator_type it_; 1411 }; 1412 #endif 1413 1414 BOOST_UBLAS_INLINE begin() const1415 const_iterator begin () const { 1416 return const_iterator (*this, 0); 1417 } 1418 BOOST_UBLAS_INLINE cbegin() const1419 const_iterator cbegin () const { 1420 return begin (); 1421 } 1422 BOOST_UBLAS_INLINE end() const1423 const_iterator end () const { 1424 return const_iterator (*this, size_); 1425 } 1426 BOOST_UBLAS_INLINE cend() const1427 const_iterator cend () const { 1428 return end (); 1429 } 1430 1431 // Reverse iterator 1432 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 1433 1434 BOOST_UBLAS_INLINE rbegin() const1435 const_reverse_iterator rbegin () const { 1436 return const_reverse_iterator (end ()); 1437 } 1438 BOOST_UBLAS_INLINE crbegin() const1439 const_reverse_iterator crbegin () const { 1440 return rbegin (); 1441 } 1442 BOOST_UBLAS_INLINE rend() const1443 const_reverse_iterator rend () const { 1444 return const_reverse_iterator (begin ()); 1445 } 1446 BOOST_UBLAS_INLINE crend() const1447 const_reverse_iterator crend () const { 1448 return rend (); 1449 } 1450 1451 BOOST_UBLAS_INLINE preprocess(size_type size) const1452 basic_slice preprocess (size_type size) const { 1453 if (this != &all_) 1454 return *this; 1455 return basic_slice (0, 1, size); 1456 } 1457 static 1458 BOOST_UBLAS_INLINE all()1459 const basic_slice &all () { 1460 return all_; 1461 } 1462 1463 private: 1464 size_type start_; 1465 difference_type stride_; 1466 size_type size_; 1467 static const basic_slice all_; 1468 }; 1469 1470 template <class Z, class D> 1471 const basic_slice<Z,D> basic_slice<Z,D>::all_ (0, 1, size_type (-1)); 1472 1473 1474 // Indirect array class 1475 template<class A> 1476 class indirect_array { 1477 typedef indirect_array<A> self_type; 1478 public: 1479 typedef A array_type; 1480 typedef const A const_array_type; 1481 typedef typename A::size_type size_type; 1482 typedef typename A::difference_type difference_type; 1483 typedef typename A::value_type value_type; 1484 typedef typename A::const_reference const_reference; 1485 typedef typename A::reference reference; 1486 typedef typename A::const_pointer const_pointer; 1487 typedef typename A::pointer pointer; 1488 1489 // Construction and destruction 1490 BOOST_UBLAS_INLINE indirect_array()1491 indirect_array (): 1492 size_ (), data_ () {} 1493 explicit BOOST_UBLAS_INLINE indirect_array(size_type size)1494 indirect_array (size_type size): 1495 size_ (size), data_ (size) {} 1496 BOOST_UBLAS_INLINE indirect_array(size_type size,const array_type & data)1497 indirect_array (size_type size, const array_type &data): 1498 size_ (size), data_ (data) {} 1499 BOOST_UBLAS_INLINE indirect_array(pointer start,pointer stop)1500 indirect_array (pointer start, pointer stop): 1501 size_ (stop - start), data_ (stop - start) { 1502 std::copy (start, stop, data_.begin ()); 1503 } 1504 1505 BOOST_UBLAS_INLINE size() const1506 size_type size () const { 1507 return size_; 1508 } 1509 BOOST_UBLAS_INLINE data() const1510 const_array_type data () const { 1511 return data_; 1512 } 1513 BOOST_UBLAS_INLINE data()1514 array_type data () { 1515 return data_; 1516 } 1517 1518 // Random Access Container 1519 BOOST_UBLAS_INLINE max_size() const1520 size_type max_size () const { 1521 return size_; 1522 } 1523 1524 BOOST_UBLAS_INLINE empty() const1525 bool empty () const { 1526 return data_.size () == 0; 1527 } 1528 1529 // Element access 1530 BOOST_UBLAS_INLINE operator ()(size_type i) const1531 const_reference operator () (size_type i) const { 1532 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 1533 return data_ [i]; 1534 } 1535 BOOST_UBLAS_INLINE operator ()(size_type i)1536 reference operator () (size_type i) { 1537 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 1538 return data_ [i]; 1539 } 1540 1541 BOOST_UBLAS_INLINE operator [](size_type i) const1542 const_reference operator [] (size_type i) const { 1543 return (*this) (i); 1544 } 1545 BOOST_UBLAS_INLINE operator [](size_type i)1546 reference operator [] (size_type i) { 1547 return (*this) (i); 1548 } 1549 1550 // Composition 1551 BOOST_UBLAS_INLINE compose(const basic_range<size_type,difference_type> & r) const1552 indirect_array compose (const basic_range<size_type, difference_type> &r) const { 1553 BOOST_UBLAS_CHECK (r.start () + r.size () <= size_, bad_size ()); 1554 array_type data (r.size ()); 1555 for (size_type i = 0; i < r.size (); ++ i) 1556 data [i] = data_ [r.start () + i]; 1557 return indirect_array (r.size (), data); 1558 } 1559 BOOST_UBLAS_INLINE compose(const basic_slice<size_type,difference_type> & s) const1560 indirect_array compose (const basic_slice<size_type, difference_type> &s) const { 1561 BOOST_UBLAS_CHECK (s.start () + s.stride () * (s.size () - (s.size () > 0)) <= size (), bad_size ()); 1562 array_type data (s.size ()); 1563 for (size_type i = 0; i < s.size (); ++ i) 1564 data [i] = data_ [s.start () + s.stride () * i]; 1565 return indirect_array (s.size (), data); 1566 } 1567 BOOST_UBLAS_INLINE compose(const indirect_array & ia) const1568 indirect_array compose (const indirect_array &ia) const { 1569 array_type data (ia.size_); 1570 for (size_type i = 0; i < ia.size_; ++ i) { 1571 BOOST_UBLAS_CHECK (ia.data_ [i] <= size_, bad_size ()); 1572 data [i] = data_ [ia.data_ [i]]; 1573 } 1574 return indirect_array (ia.size_, data); 1575 } 1576 1577 // Comparison 1578 template<class OA> 1579 BOOST_UBLAS_INLINE operator ==(const indirect_array<OA> & ia) const1580 bool operator == (const indirect_array<OA> &ia) const { 1581 if (size_ != ia.size_) 1582 return false; 1583 for (size_type i = 0; i < BOOST_UBLAS_SAME (size_, ia.size_); ++ i) 1584 if (data_ [i] != ia.data_ [i]) 1585 return false; 1586 return true; 1587 } 1588 template<class OA> 1589 BOOST_UBLAS_INLINE operator !=(const indirect_array<OA> & ia) const1590 bool operator != (const indirect_array<OA> &ia) const { 1591 return ! (*this == ia); 1592 } 1593 1594 // Iterator types 1595 private: 1596 // Use a index difference 1597 typedef difference_type const_subiterator_type; 1598 1599 public: 1600 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1601 typedef indexed_const_iterator<indirect_array, std::random_access_iterator_tag> const_iterator; 1602 #else 1603 class const_iterator: 1604 public container_const_reference<indirect_array>, 1605 public random_access_iterator_base<std::random_access_iterator_tag, 1606 const_iterator, value_type> { 1607 public: 1608 typedef typename indirect_array::value_type value_type; 1609 typedef typename indirect_array::difference_type difference_type; 1610 typedef typename indirect_array::const_reference reference; 1611 typedef typename indirect_array::const_pointer pointer; 1612 1613 // Construction and destruction 1614 BOOST_UBLAS_INLINE 1615 const_iterator (): 1616 container_const_reference<indirect_array> (), it_ () {} 1617 BOOST_UBLAS_INLINE 1618 const_iterator (const indirect_array &ia, const const_subiterator_type &it): 1619 container_const_reference<indirect_array> (ia), it_ (it) {} 1620 1621 // Arithmetic 1622 BOOST_UBLAS_INLINE 1623 const_iterator &operator ++ () { 1624 ++ it_; 1625 return *this; 1626 } 1627 BOOST_UBLAS_INLINE 1628 const_iterator &operator -- () { 1629 -- it_; 1630 return *this; 1631 } 1632 BOOST_UBLAS_INLINE 1633 const_iterator &operator += (difference_type n) { 1634 it_ += n; 1635 return *this; 1636 } 1637 BOOST_UBLAS_INLINE 1638 const_iterator &operator -= (difference_type n) { 1639 it_ -= n; 1640 return *this; 1641 } 1642 BOOST_UBLAS_INLINE 1643 difference_type operator - (const const_iterator &it) const { 1644 return it_ - it.it_; 1645 } 1646 1647 // Dereference 1648 BOOST_UBLAS_INLINE 1649 const_reference operator * () const { 1650 return (*this) () (it_); 1651 } 1652 1653 BOOST_UBLAS_INLINE 1654 const_reference operator [] (difference_type n) const { 1655 return *(*this + n); 1656 } 1657 1658 // Index 1659 BOOST_UBLAS_INLINE 1660 size_type index () const { 1661 return it_; 1662 } 1663 1664 // Assignment 1665 BOOST_UBLAS_INLINE 1666 const_iterator &operator = (const const_iterator &it) { 1667 // Comeau recommends... 1668 this->assign (&it ()); 1669 it_ = it.it_; 1670 return *this; 1671 } 1672 1673 // Comparison 1674 BOOST_UBLAS_INLINE 1675 bool operator == (const const_iterator &it) const { 1676 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 1677 return it_ == it.it_; 1678 } 1679 BOOST_UBLAS_INLINE 1680 bool operator < (const const_iterator &it) const { 1681 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 1682 return it_ < it.it_; 1683 } 1684 1685 private: 1686 const_subiterator_type it_; 1687 }; 1688 #endif 1689 1690 BOOST_UBLAS_INLINE begin() const1691 const_iterator begin () const { 1692 return const_iterator (*this, 0); 1693 } 1694 BOOST_UBLAS_INLINE cbegin() const1695 const_iterator cbegin () const { 1696 return begin (); 1697 } 1698 BOOST_UBLAS_INLINE end() const1699 const_iterator end () const { 1700 return const_iterator (*this, size_); 1701 } 1702 BOOST_UBLAS_INLINE cend() const1703 const_iterator cend () const { 1704 return end (); 1705 } 1706 1707 // Reverse iterator 1708 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 1709 1710 BOOST_UBLAS_INLINE rbegin() const1711 const_reverse_iterator rbegin () const { 1712 return const_reverse_iterator (end ()); 1713 } 1714 BOOST_UBLAS_INLINE crbegin() const1715 const_reverse_iterator crbegin () const { 1716 return rbegin (); 1717 } 1718 BOOST_UBLAS_INLINE rend() const1719 const_reverse_iterator rend () const { 1720 return const_reverse_iterator (begin ()); 1721 } 1722 BOOST_UBLAS_INLINE crend() const1723 const_reverse_iterator crend () const { 1724 return rend (); 1725 } 1726 1727 BOOST_UBLAS_INLINE preprocess(size_type size) const1728 indirect_array preprocess (size_type size) const { 1729 if (this != &all_) 1730 return *this; 1731 indirect_array ia (size); 1732 for (size_type i = 0; i < size; ++ i) 1733 ia (i) = i; 1734 return ia; 1735 } 1736 static 1737 BOOST_UBLAS_INLINE all()1738 const indirect_array &all () { 1739 return all_; 1740 } 1741 1742 private: 1743 size_type size_; 1744 array_type data_; 1745 static const indirect_array all_; 1746 }; 1747 1748 template<class A> 1749 const indirect_array<A> indirect_array<A>::all_; 1750 1751 1752 1753 // Gunter Winkler contributed the classes index_pair, index_pair_array, 1754 // index_triple and index_triple_array to enable inplace sort of parallel arrays. 1755 1756 template <class V> 1757 class index_pair : 1758 public container_reference<V> { 1759 1760 typedef index_pair<V> self_type; 1761 public: 1762 typedef typename V::size_type size_type; 1763 1764 BOOST_UBLAS_INLINE index_pair(V & v,size_type i)1765 index_pair(V& v, size_type i) : 1766 container_reference<V>(v), i_(i), 1767 v1_(v.data1_[i]), v2_(v.data2_[i]), 1768 dirty_(false), is_copy_(false) {} 1769 BOOST_UBLAS_INLINE index_pair(const self_type & rhs)1770 index_pair(const self_type& rhs) : 1771 container_reference<V>(rhs()), i_(0), 1772 v1_(rhs.v1_), v2_(rhs.v2_), 1773 dirty_(false), is_copy_(true) {} 1774 BOOST_UBLAS_INLINE ~index_pair()1775 ~index_pair() { 1776 if (dirty_ && (!is_copy_) ) { 1777 (*this)().data1_[i_] = v1_; 1778 (*this)().data2_[i_] = v2_; 1779 } 1780 } 1781 1782 BOOST_UBLAS_INLINE operator =(const self_type & rhs)1783 self_type& operator=(const self_type& rhs) { 1784 v1_ = rhs.v1_; 1785 v2_ = rhs.v2_; 1786 dirty_ = true; 1787 return *this; 1788 } 1789 1790 BOOST_UBLAS_INLINE swap(self_type & rhs)1791 void swap(self_type& rhs) { 1792 self_type tmp(rhs); 1793 rhs = *this; 1794 *this = tmp; 1795 } 1796 1797 BOOST_UBLAS_INLINE swap(self_type & lhs,self_type & rhs)1798 friend void swap(self_type& lhs, self_type& rhs) { 1799 lhs.swap(rhs); 1800 } 1801 swap(self_type lhs,self_type rhs)1802 friend void swap(self_type lhs, self_type rhs) { // For gcc 4.8 and c++11 1803 lhs.swap(rhs); 1804 } 1805 1806 1807 BOOST_UBLAS_INLINE equal(const self_type & rhs) const1808 bool equal(const self_type& rhs) const { 1809 return (v1_ == rhs.v1_); 1810 } 1811 BOOST_UBLAS_INLINE less(const self_type & rhs) const1812 bool less(const self_type& rhs) const { 1813 return (v1_ < rhs.v1_); 1814 } 1815 BOOST_UBLAS_INLINE operator ==(const self_type & lhs,const self_type & rhs)1816 friend bool operator == (const self_type& lhs, const self_type& rhs) { 1817 return lhs.equal(rhs); 1818 } 1819 BOOST_UBLAS_INLINE operator !=(const self_type & lhs,const self_type & rhs)1820 friend bool operator != (const self_type& lhs, const self_type& rhs) { 1821 return !lhs.equal(rhs); 1822 } 1823 BOOST_UBLAS_INLINE operator <(const self_type & lhs,const self_type & rhs)1824 friend bool operator < (const self_type& lhs, const self_type& rhs) { 1825 return lhs.less(rhs); 1826 } 1827 BOOST_UBLAS_INLINE operator >=(const self_type & lhs,const self_type & rhs)1828 friend bool operator >= (const self_type& lhs, const self_type& rhs) { 1829 return !lhs.less(rhs); 1830 } 1831 BOOST_UBLAS_INLINE operator >(const self_type & lhs,const self_type & rhs)1832 friend bool operator > (const self_type& lhs, const self_type& rhs) { 1833 return rhs.less(lhs); 1834 } 1835 BOOST_UBLAS_INLINE operator <=(const self_type & lhs,const self_type & rhs)1836 friend bool operator <= (const self_type& lhs, const self_type& rhs) { 1837 return !rhs.less(lhs); 1838 } 1839 1840 private: 1841 size_type i_; 1842 typename V::value1_type v1_; 1843 typename V::value2_type v2_; 1844 bool dirty_; 1845 bool is_copy_; 1846 }; 1847 1848 template <class V1, class V2> 1849 class index_pair_array: 1850 private boost::noncopyable { 1851 1852 typedef index_pair_array<V1, V2> self_type; 1853 public: 1854 typedef typename V1::value_type value1_type; 1855 typedef typename V2::value_type value2_type; 1856 1857 typedef typename V1::size_type size_type; 1858 typedef typename V1::difference_type difference_type; 1859 typedef index_pair<self_type> value_type; 1860 // There is nothing that can be referenced directly. Always return a copy of the index_pair 1861 typedef value_type reference; 1862 typedef const value_type const_reference; 1863 1864 BOOST_UBLAS_INLINE index_pair_array(size_type size,V1 & data1,V2 & data2)1865 index_pair_array(size_type size, V1& data1, V2& data2) : 1866 size_(size),data1_(data1),data2_(data2) {} 1867 1868 BOOST_UBLAS_INLINE size() const1869 size_type size() const { 1870 return size_; 1871 } 1872 1873 BOOST_UBLAS_INLINE operator ()(size_type i) const1874 const_reference operator () (size_type i) const { 1875 return value_type((*this), i); 1876 } 1877 BOOST_UBLAS_INLINE operator ()(size_type i)1878 reference operator () (size_type i) { 1879 return value_type((*this), i); 1880 } 1881 1882 typedef indexed_iterator<self_type, std::random_access_iterator_tag> iterator; 1883 typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator; 1884 1885 BOOST_UBLAS_INLINE begin()1886 iterator begin() { 1887 return iterator( (*this), 0); 1888 } 1889 BOOST_UBLAS_INLINE end()1890 iterator end() { 1891 return iterator( (*this), size()); 1892 } 1893 1894 BOOST_UBLAS_INLINE begin() const1895 const_iterator begin() const { 1896 return const_iterator( (*this), 0); 1897 } 1898 BOOST_UBLAS_INLINE cbegin() const1899 const_iterator cbegin () const { 1900 return begin (); 1901 } 1902 BOOST_UBLAS_INLINE end() const1903 const_iterator end() const { 1904 return const_iterator( (*this), size()); 1905 } 1906 BOOST_UBLAS_INLINE cend() const1907 const_iterator cend () const { 1908 return end (); 1909 } 1910 1911 // unnecessary function: 1912 BOOST_UBLAS_INLINE equal(size_type i1,size_type i2) const1913 bool equal(size_type i1, size_type i2) const { 1914 return data1_[i1] == data1_[i2]; 1915 } 1916 BOOST_UBLAS_INLINE less(size_type i1,size_type i2) const1917 bool less(size_type i1, size_type i2) const { 1918 return data1_[i1] < data1_[i2]; 1919 } 1920 1921 // gives a large speedup 1922 BOOST_UBLAS_INLINE iter_swap(const iterator & lhs,const iterator & rhs)1923 friend void iter_swap(const iterator& lhs, const iterator& rhs) { 1924 const size_type i1 = lhs.index(); 1925 const size_type i2 = rhs.index(); 1926 std::swap(lhs().data1_[i1], rhs().data1_[i2]); 1927 std::swap(lhs().data2_[i1], rhs().data2_[i2]); 1928 } 1929 1930 private: 1931 size_type size_; 1932 V1& data1_; 1933 V2& data2_; 1934 1935 // friend class value_type; 1936 friend class index_pair<self_type>; 1937 }; 1938 1939 template <class M> 1940 class index_triple : 1941 public container_reference<M> { 1942 1943 typedef index_triple<M> self_type; 1944 public: 1945 typedef typename M::size_type size_type; 1946 1947 BOOST_UBLAS_INLINE index_triple(M & m,size_type i)1948 index_triple(M& m, size_type i) : 1949 container_reference<M>(m), i_(i), 1950 v1_(m.data1_[i]), v2_(m.data2_[i]), v3_(m.data3_[i]), 1951 dirty_(false), is_copy_(false) {} 1952 BOOST_UBLAS_INLINE index_triple(const self_type & rhs)1953 index_triple(const self_type& rhs) : 1954 container_reference<M>(rhs()), i_(0), 1955 v1_(rhs.v1_), v2_(rhs.v2_), v3_(rhs.v3_), 1956 dirty_(false), is_copy_(true) {} 1957 BOOST_UBLAS_INLINE ~index_triple()1958 ~index_triple() { 1959 if (dirty_ && (!is_copy_) ) { 1960 (*this)().data1_[i_] = v1_; 1961 (*this)().data2_[i_] = v2_; 1962 (*this)().data3_[i_] = v3_; 1963 } 1964 } 1965 1966 BOOST_UBLAS_INLINE operator =(const self_type & rhs)1967 self_type& operator=(const self_type& rhs) { 1968 v1_ = rhs.v1_; 1969 v2_ = rhs.v2_; 1970 v3_ = rhs.v3_; 1971 dirty_ = true; 1972 return *this; 1973 } 1974 1975 BOOST_UBLAS_INLINE swap(self_type & rhs)1976 void swap(self_type& rhs) { 1977 self_type tmp(rhs); 1978 rhs = *this; 1979 *this = tmp; 1980 } 1981 1982 BOOST_UBLAS_INLINE swap(self_type & lhs,self_type & rhs)1983 friend void swap(self_type& lhs, self_type& rhs) { 1984 lhs.swap(rhs); 1985 } 1986 swap(self_type lhs,self_type rhs)1987 friend void swap(self_type lhs, self_type rhs) { // For gcc 4.8 and c++11 1988 lhs.swap(rhs); 1989 } 1990 1991 BOOST_UBLAS_INLINE equal(const self_type & rhs) const1992 bool equal(const self_type& rhs) const { 1993 return ((v1_ == rhs.v1_) && (v2_ == rhs.v2_)); 1994 } 1995 BOOST_UBLAS_INLINE less(const self_type & rhs) const1996 bool less(const self_type& rhs) const { 1997 return ((v1_ < rhs.v1_) || 1998 (v1_ == rhs.v1_ && v2_ < rhs.v2_)); 1999 } 2000 BOOST_UBLAS_INLINE operator ==(const self_type & lhs,const self_type & rhs)2001 friend bool operator == (const self_type& lhs, const self_type& rhs) { 2002 return lhs.equal(rhs); 2003 } 2004 BOOST_UBLAS_INLINE operator !=(const self_type & lhs,const self_type & rhs)2005 friend bool operator != (const self_type& lhs, const self_type& rhs) { 2006 return !lhs.equal(rhs); 2007 } 2008 BOOST_UBLAS_INLINE operator <(const self_type & lhs,const self_type & rhs)2009 friend bool operator < (const self_type& lhs, const self_type& rhs) { 2010 return lhs.less(rhs); 2011 } 2012 BOOST_UBLAS_INLINE operator >=(const self_type & lhs,const self_type & rhs)2013 friend bool operator >= (const self_type& lhs, const self_type& rhs) { 2014 return !lhs.less(rhs); 2015 } 2016 BOOST_UBLAS_INLINE operator >(const self_type & lhs,const self_type & rhs)2017 friend bool operator > (const self_type& lhs, const self_type& rhs) { 2018 return rhs.less(lhs); 2019 } 2020 BOOST_UBLAS_INLINE operator <=(const self_type & lhs,const self_type & rhs)2021 friend bool operator <= (const self_type& lhs, const self_type& rhs) { 2022 return !rhs.less(lhs); 2023 } 2024 2025 private: 2026 size_type i_; 2027 typename M::value1_type v1_; 2028 typename M::value2_type v2_; 2029 typename M::value3_type v3_; 2030 bool dirty_; 2031 bool is_copy_; 2032 }; 2033 2034 template <class V1, class V2, class V3> 2035 class index_triple_array: 2036 private boost::noncopyable { 2037 2038 typedef index_triple_array<V1, V2, V3> self_type; 2039 public: 2040 typedef typename V1::value_type value1_type; 2041 typedef typename V2::value_type value2_type; 2042 typedef typename V3::value_type value3_type; 2043 2044 typedef typename V1::size_type size_type; 2045 typedef typename V1::difference_type difference_type; 2046 typedef index_triple<self_type> value_type; 2047 // There is nothing that can be referenced directly. Always return a copy of the index_triple 2048 typedef value_type reference; 2049 typedef const value_type const_reference; 2050 2051 BOOST_UBLAS_INLINE index_triple_array(size_type size,V1 & data1,V2 & data2,V3 & data3)2052 index_triple_array(size_type size, V1& data1, V2& data2, V3& data3) : 2053 size_(size),data1_(data1),data2_(data2),data3_(data3) {} 2054 2055 BOOST_UBLAS_INLINE size() const2056 size_type size() const { 2057 return size_; 2058 } 2059 2060 BOOST_UBLAS_INLINE operator ()(size_type i) const2061 const_reference operator () (size_type i) const { 2062 return value_type((*this), i); 2063 } 2064 BOOST_UBLAS_INLINE operator ()(size_type i)2065 reference operator () (size_type i) { 2066 return value_type((*this), i); 2067 } 2068 2069 typedef indexed_iterator<self_type, std::random_access_iterator_tag> iterator; 2070 typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator; 2071 2072 BOOST_UBLAS_INLINE begin()2073 iterator begin() { 2074 return iterator( (*this), 0); 2075 } 2076 BOOST_UBLAS_INLINE end()2077 iterator end() { 2078 return iterator( (*this), size()); 2079 } 2080 2081 BOOST_UBLAS_INLINE begin() const2082 const_iterator begin() const { 2083 return const_iterator( (*this), 0); 2084 } 2085 BOOST_UBLAS_INLINE cbegin() const2086 const_iterator cbegin () const { 2087 return begin (); 2088 } 2089 BOOST_UBLAS_INLINE end() const2090 const_iterator end() const { 2091 return const_iterator( (*this), size()); 2092 } 2093 BOOST_UBLAS_INLINE cend() const2094 const_iterator cend () const { 2095 return end (); 2096 } 2097 2098 // unnecessary function: 2099 BOOST_UBLAS_INLINE equal(size_type i1,size_type i2) const2100 bool equal(size_type i1, size_type i2) const { 2101 return ((data1_[i1] == data1_[i2]) && (data2_[i1] == data2_[i2])); 2102 } 2103 BOOST_UBLAS_INLINE less(size_type i1,size_type i2) const2104 bool less(size_type i1, size_type i2) const { 2105 return ((data1_[i1] < data1_[i2]) || 2106 (data1_[i1] == data1_[i2] && data2_[i1] < data2_[i2])); 2107 } 2108 2109 // gives a large speedup 2110 BOOST_UBLAS_INLINE iter_swap(const iterator & lhs,const iterator & rhs)2111 friend void iter_swap(const iterator& lhs, const iterator& rhs) { 2112 const size_type i1 = lhs.index(); 2113 const size_type i2 = rhs.index(); 2114 std::swap(lhs().data1_[i1], rhs().data1_[i2]); 2115 std::swap(lhs().data2_[i1], rhs().data2_[i2]); 2116 std::swap(lhs().data3_[i1], rhs().data3_[i2]); 2117 } 2118 2119 private: 2120 size_type size_; 2121 V1& data1_; 2122 V2& data2_; 2123 V3& data3_; 2124 2125 // friend class value_type; 2126 friend class index_triple<self_type>; 2127 }; 2128 2129 }}} 2130 2131 #endif 2132