...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
00001 // 00002 // Copyright (c) 2000-2002 00003 // Joerg Walter, Mathias Koch 00004 // 00005 // Distributed under the Boost Software License, Version 1.0. (See 00006 // accompanying file LICENSE_1_0.txt or copy at 00007 // http://www.boost.org/LICENSE_1_0.txt) 00008 // 00009 // The authors gratefully acknowledge the support of 00010 // GeNeSys mbH & Co. KG in producing this work. 00011 // 00012 00013 #ifndef BOOST_UBLAS_STORAGE_H 00014 #define BOOST_UBLAS_STORAGE_H 00015 00016 #include <algorithm> 00017 #ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR 00018 #include <boost/shared_array.hpp> 00019 #endif 00020 00021 #include <boost/serialization/array.hpp> 00022 #include <boost/serialization/collection_size_type.hpp> 00023 #include <boost/serialization/nvp.hpp> 00024 00025 #include <boost/numeric/ublas/exception.hpp> 00026 #include <boost/numeric/ublas/traits.hpp> 00027 #include <boost/numeric/ublas/detail/iterator.hpp> 00028 00029 00030 namespace boost { namespace numeric { namespace ublas { 00031 00032 00033 // Base class for Storage Arrays - see the Barton Nackman trick 00034 template<class E> 00035 class storage_array: 00036 private nonassignable { 00037 }; 00038 00039 00040 // Unbounded array - with allocator 00041 template<class T, class ALLOC> 00042 class unbounded_array: 00043 public storage_array<unbounded_array<T, ALLOC> > { 00044 00045 typedef unbounded_array<T, ALLOC> self_type; 00046 public: 00047 typedef ALLOC allocator_type; 00048 typedef typename ALLOC::size_type size_type; 00049 typedef typename ALLOC::difference_type difference_type; 00050 typedef T value_type; 00051 typedef const T &const_reference; 00052 typedef T &reference; 00053 typedef const T *const_pointer; 00054 typedef T *pointer; 00055 typedef const_pointer const_iterator; 00056 typedef pointer iterator; 00057 00058 // Construction and destruction 00059 explicit BOOST_UBLAS_INLINE 00060 unbounded_array (const ALLOC &a = ALLOC()): 00061 alloc_ (a), size_ (0) { 00062 data_ = 0; 00063 } 00064 explicit BOOST_UBLAS_INLINE 00065 unbounded_array (size_type size, const ALLOC &a = ALLOC()): 00066 alloc_(a), size_ (size) { 00067 if (size_) { 00068 data_ = alloc_.allocate (size_); 00069 if (! detail::has_trivial_constructor<T>::value) { 00070 for (pointer d = data_; d != data_ + size_; ++d) 00071 alloc_.construct(d, value_type()); 00072 } 00073 } 00074 else 00075 data_ = 0; 00076 } 00077 // No value initialised, but still be default constructed 00078 BOOST_UBLAS_INLINE 00079 unbounded_array (size_type size, const value_type &init, const ALLOC &a = ALLOC()): 00080 alloc_ (a), size_ (size) { 00081 if (size_) { 00082 data_ = alloc_.allocate (size_); 00083 std::uninitialized_fill (begin(), end(), init); 00084 } 00085 else 00086 data_ = 0; 00087 } 00088 BOOST_UBLAS_INLINE 00089 unbounded_array (const unbounded_array &c): 00090 storage_array<unbounded_array<T, ALLOC> >(), 00091 alloc_ (c.alloc_), size_ (c.size_) { 00092 if (size_) { 00093 data_ = alloc_.allocate (size_); 00094 std::uninitialized_copy (c.begin(), c.end(), begin()); 00095 } 00096 else 00097 data_ = 0; 00098 } 00099 BOOST_UBLAS_INLINE 00100 ~unbounded_array () { 00101 if (size_) { 00102 if (! detail::has_trivial_destructor<T>::value) { 00103 // std::_Destroy (begin(), end(), alloc_); 00104 const iterator i_end = end(); 00105 for (iterator i = begin (); i != i_end; ++i) { 00106 iterator_destroy (i); 00107 } 00108 } 00109 alloc_.deallocate (data_, size_); 00110 } 00111 } 00112 00113 // Resizing 00114 private: 00115 BOOST_UBLAS_INLINE 00116 void resize_internal (const size_type size, const value_type init, const bool preserve) { 00117 if (size != size_) { 00118 pointer p_data = data_; 00119 if (size) { 00120 data_ = alloc_.allocate (size); 00121 if (preserve) { 00122 pointer si = p_data; 00123 pointer di = data_; 00124 if (size < size_) { 00125 for (; di != data_ + size; ++di) { 00126 alloc_.construct (di, *si); 00127 ++si; 00128 } 00129 } 00130 else { 00131 for (pointer si = p_data; si != p_data + size_; ++si) { 00132 alloc_.construct (di, *si); 00133 ++di; 00134 } 00135 for (; di != data_ + size; ++di) { 00136 alloc_.construct (di, init); 00137 } 00138 } 00139 } 00140 else { 00141 if (! detail::has_trivial_constructor<T>::value) { 00142 for (pointer di = data_; di != data_ + size; ++di) 00143 alloc_.construct (di, value_type()); 00144 } 00145 } 00146 } 00147 00148 if (size_) { 00149 if (! detail::has_trivial_destructor<T>::value) { 00150 for (pointer si = p_data; si != p_data + size_; ++si) 00151 alloc_.destroy (si); 00152 } 00153 alloc_.deallocate (p_data, size_); 00154 } 00155 00156 if (!size) 00157 data_ = 0; 00158 size_ = size; 00159 } 00160 } 00161 public: 00162 BOOST_UBLAS_INLINE 00163 void resize (size_type size) { 00164 resize_internal (size, value_type (), false); 00165 } 00166 BOOST_UBLAS_INLINE 00167 void resize (size_type size, value_type init) { 00168 resize_internal (size, init, true); 00169 } 00170 00171 // Random Access Container 00172 BOOST_UBLAS_INLINE 00173 size_type max_size () const { 00174 return ALLOC ().max_size(); 00175 } 00176 00177 BOOST_UBLAS_INLINE 00178 bool empty () const { 00179 return size_ == 0; 00180 } 00181 00182 BOOST_UBLAS_INLINE 00183 size_type size () const { 00184 return size_; 00185 } 00186 00187 // Element access 00188 BOOST_UBLAS_INLINE 00189 const_reference operator [] (size_type i) const { 00190 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 00191 return data_ [i]; 00192 } 00193 BOOST_UBLAS_INLINE 00194 reference operator [] (size_type i) { 00195 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 00196 return data_ [i]; 00197 } 00198 00199 // Assignment 00200 BOOST_UBLAS_INLINE 00201 unbounded_array &operator = (const unbounded_array &a) { 00202 if (this != &a) { 00203 resize (a.size_); 00204 std::copy (a.data_, a.data_ + a.size_, data_); 00205 } 00206 return *this; 00207 } 00208 BOOST_UBLAS_INLINE 00209 unbounded_array &assign_temporary (unbounded_array &a) { 00210 swap (a); 00211 return *this; 00212 } 00213 00214 // Swapping 00215 BOOST_UBLAS_INLINE 00216 void swap (unbounded_array &a) { 00217 if (this != &a) { 00218 std::swap (size_, a.size_); 00219 std::swap (data_, a.data_); 00220 } 00221 } 00222 BOOST_UBLAS_INLINE 00223 friend void swap (unbounded_array &a1, unbounded_array &a2) { 00224 a1.swap (a2); 00225 } 00226 00227 BOOST_UBLAS_INLINE 00228 const_iterator begin () const { 00229 return data_; 00230 } 00231 BOOST_UBLAS_INLINE 00232 const_iterator end () const { 00233 return data_ + size_; 00234 } 00235 00236 BOOST_UBLAS_INLINE 00237 iterator begin () { 00238 return data_; 00239 } 00240 BOOST_UBLAS_INLINE 00241 iterator end () { 00242 return data_ + size_; 00243 } 00244 00245 // Reverse iterators 00246 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00247 typedef std::reverse_iterator<iterator> reverse_iterator; 00248 00249 BOOST_UBLAS_INLINE 00250 const_reverse_iterator rbegin () const { 00251 return const_reverse_iterator (end ()); 00252 } 00253 BOOST_UBLAS_INLINE 00254 const_reverse_iterator rend () const { 00255 return const_reverse_iterator (begin ()); 00256 } 00257 BOOST_UBLAS_INLINE 00258 reverse_iterator rbegin () { 00259 return reverse_iterator (end ()); 00260 } 00261 BOOST_UBLAS_INLINE 00262 reverse_iterator rend () { 00263 return reverse_iterator (begin ()); 00264 } 00265 00266 // Allocator 00267 allocator_type get_allocator () { 00268 return alloc_; 00269 } 00270 00271 private: 00272 friend class boost::serialization::access; 00273 00274 // Serialization 00275 template<class Archive> 00276 void serialize(Archive & ar, const unsigned int version) 00277 { 00278 serialization::collection_size_type s(size_); 00279 ar & serialization::make_nvp("size",s); 00280 if ( Archive::is_loading::value ) { 00281 resize(s); 00282 } 00283 ar & serialization::make_array(data_, s); 00284 } 00285 00286 private: 00287 // Handle explict destroy on a (possibly indexed) iterator 00288 BOOST_UBLAS_INLINE 00289 static void iterator_destroy (iterator &i) { 00290 (&(*i)) -> ~value_type (); 00291 } 00292 ALLOC alloc_; 00293 size_type size_; 00294 pointer data_; 00295 }; 00296 00297 // Bounded array - with allocator for size_type and difference_type 00298 template<class T, std::size_t N, class ALLOC> 00299 class bounded_array: 00300 public storage_array<bounded_array<T, N, ALLOC> > { 00301 00302 typedef bounded_array<T, N, ALLOC> self_type; 00303 public: 00304 // No allocator_type as ALLOC is not used for allocation 00305 typedef typename ALLOC::size_type size_type; 00306 typedef typename ALLOC::difference_type difference_type; 00307 typedef T value_type; 00308 typedef const T &const_reference; 00309 typedef T &reference; 00310 typedef const T *const_pointer; 00311 typedef T *pointer; 00312 typedef const_pointer const_iterator; 00313 typedef pointer iterator; 00314 00315 // Construction and destruction 00316 BOOST_UBLAS_INLINE 00317 bounded_array (): 00318 size_ (0) /*, data_ ()*/ { // size 0 - use bounded_vector to default construct with size N 00319 } 00320 explicit BOOST_UBLAS_INLINE 00321 bounded_array (size_type size): 00322 size_ (size) /*, data_ ()*/ { 00323 BOOST_UBLAS_CHECK (size_ <= N, bad_size ()); 00324 // data_ (an array) elements are already default constructed 00325 } 00326 BOOST_UBLAS_INLINE 00327 bounded_array (size_type size, const value_type &init): 00328 size_ (size) /*, data_ ()*/ { 00329 BOOST_UBLAS_CHECK (size_ <= N, bad_size ()); 00330 // ISSUE elements should be value constructed here, but we must fill instead as already default constructed 00331 std::fill (begin(), end(), init) ; 00332 } 00333 BOOST_UBLAS_INLINE 00334 bounded_array (const bounded_array &c): 00335 size_ (c.size_) { 00336 // ISSUE elements should be copy constructed here, but we must copy instead as already default constructed 00337 std::copy (c.begin(), c.end(), begin()); 00338 } 00339 00340 // Resizing 00341 BOOST_UBLAS_INLINE 00342 void resize (size_type size) { 00343 BOOST_UBLAS_CHECK (size <= N, bad_size ()); 00344 size_ = size; 00345 } 00346 BOOST_UBLAS_INLINE 00347 void resize (size_type size, value_type init) { 00348 BOOST_UBLAS_CHECK (size <= N, bad_size ()); 00349 if (size > size_) 00350 std::fill (data_ + size_, data_ + size, init); 00351 size_ = size; 00352 } 00353 00354 // Random Access Container 00355 BOOST_UBLAS_INLINE 00356 size_type max_size () const { 00357 return ALLOC ().max_size(); 00358 } 00359 00360 BOOST_UBLAS_INLINE 00361 bool empty () const { 00362 return size_ == 0; 00363 } 00364 00365 BOOST_UBLAS_INLINE 00366 size_type size () const { 00367 return size_; 00368 } 00369 00370 // Element access 00371 BOOST_UBLAS_INLINE 00372 const_reference operator [] (size_type i) const { 00373 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 00374 return data_ [i]; 00375 } 00376 BOOST_UBLAS_INLINE 00377 reference operator [] (size_type i) { 00378 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 00379 return data_ [i]; 00380 } 00381 00382 // Assignment 00383 BOOST_UBLAS_INLINE 00384 bounded_array &operator = (const bounded_array &a) { 00385 if (this != &a) { 00386 resize (a.size_); 00387 std::copy (a.data_, a.data_ + a.size_, data_); 00388 } 00389 return *this; 00390 } 00391 BOOST_UBLAS_INLINE 00392 bounded_array &assign_temporary (bounded_array &a) { 00393 *this = a; 00394 return *this; 00395 } 00396 00397 // Swapping 00398 BOOST_UBLAS_INLINE 00399 void swap (bounded_array &a) { 00400 if (this != &a) { 00401 std::swap (size_, a.size_); 00402 std::swap_ranges (data_, data_ + (std::max) (size_, a.size_), a.data_); 00403 } 00404 } 00405 BOOST_UBLAS_INLINE 00406 friend void swap (bounded_array &a1, bounded_array &a2) { 00407 a1.swap (a2); 00408 } 00409 00410 BOOST_UBLAS_INLINE 00411 const_iterator begin () const { 00412 return data_; 00413 } 00414 BOOST_UBLAS_INLINE 00415 const_iterator end () const { 00416 return data_ + size_; 00417 } 00418 00419 BOOST_UBLAS_INLINE 00420 iterator begin () { 00421 return data_; 00422 } 00423 BOOST_UBLAS_INLINE 00424 iterator end () { 00425 return data_ + size_; 00426 } 00427 00428 // Reverse iterators 00429 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00430 typedef std::reverse_iterator<iterator> reverse_iterator; 00431 00432 BOOST_UBLAS_INLINE 00433 const_reverse_iterator rbegin () const { 00434 return const_reverse_iterator (end ()); 00435 } 00436 BOOST_UBLAS_INLINE 00437 const_reverse_iterator rend () const { 00438 return const_reverse_iterator (begin ()); 00439 } 00440 BOOST_UBLAS_INLINE 00441 reverse_iterator rbegin () { 00442 return reverse_iterator (end ()); 00443 } 00444 BOOST_UBLAS_INLINE 00445 reverse_iterator rend () { 00446 return reverse_iterator (begin ()); 00447 } 00448 00449 private: 00450 // Serialization 00451 friend class boost::serialization::access; 00452 00453 template<class Archive> 00454 void serialize(Archive & ar, const unsigned int version) 00455 { 00456 serialization::collection_size_type s(size_); 00457 ar & serialization::make_nvp("size", s); 00458 if ( Archive::is_loading::value ) { 00459 if (s > N) bad_size("too large size in bounded_array::load()\n").raise(); 00460 resize(s); 00461 } 00462 ar & serialization::make_array(data_, s); 00463 } 00464 00465 private: 00466 size_type size_; 00467 BOOST_UBLAS_BOUNDED_ARRAY_ALIGN value_type data_ [N]; 00468 }; 00469 00470 00471 // Array adaptor with normal deep copy semantics of elements 00472 template<class T> 00473 class array_adaptor: 00474 public storage_array<array_adaptor<T> > { 00475 00476 typedef array_adaptor<T> self_type; 00477 public: 00478 typedef std::size_t size_type; 00479 typedef std::ptrdiff_t difference_type; 00480 typedef T value_type; 00481 typedef const T &const_reference; 00482 typedef T &reference; 00483 typedef const T *const_pointer; 00484 typedef T *pointer; 00485 00486 // Construction and destruction 00487 BOOST_UBLAS_INLINE 00488 array_adaptor (): 00489 size_ (0), own_ (true), data_ (new value_type [0]) { 00490 } 00491 explicit BOOST_UBLAS_INLINE 00492 array_adaptor (size_type size): 00493 size_ (size), own_ (true), data_ (new value_type [size]) { 00494 } 00495 BOOST_UBLAS_INLINE 00496 array_adaptor (size_type size, const value_type &init): 00497 size_ (size), own_ (true), data_ (new value_type [size]) { 00498 std::fill (data_, data_ + size_, init); 00499 } 00500 BOOST_UBLAS_INLINE 00501 array_adaptor (size_type size, pointer data): 00502 size_ (size), own_ (false), data_ (data) {} 00503 BOOST_UBLAS_INLINE 00504 array_adaptor (const array_adaptor &a): 00505 storage_array<self_type> (), 00506 size_ (a.size_), own_ (true), data_ (new value_type [a.size_]) { 00507 *this = a; 00508 } 00509 BOOST_UBLAS_INLINE 00510 ~array_adaptor () { 00511 if (own_) { 00512 delete [] data_; 00513 } 00514 } 00515 00516 // Resizing 00517 private: 00518 BOOST_UBLAS_INLINE 00519 void resize_internal (size_type size, value_type init, bool preserve = true) { 00520 if (size != size_) { 00521 pointer data = new value_type [size]; 00522 if (preserve) { 00523 std::copy (data_, data_ + (std::min) (size, size_), data); 00524 std::fill (data + (std::min) (size, size_), data + size, init); 00525 } 00526 if (own_) 00527 delete [] data_; 00528 size_ = size; 00529 own_ = true; 00530 data_ = data; 00531 } 00532 } 00533 BOOST_UBLAS_INLINE 00534 void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) { 00535 if (data != data_) { 00536 if (preserve) { 00537 std::copy (data_, data_ + (std::min) (size, size_), data); 00538 std::fill (data + (std::min) (size, size_), data + size, init); 00539 } 00540 if (own_) 00541 delete [] data_; 00542 own_ = false; 00543 data_ = data; 00544 } 00545 else { 00546 std::fill (data + (std::min) (size, size_), data + size, init); 00547 } 00548 size_ = size; 00549 } 00550 public: 00551 BOOST_UBLAS_INLINE 00552 void resize (size_type size) { 00553 resize_internal (size, value_type (), false); 00554 } 00555 BOOST_UBLAS_INLINE 00556 void resize (size_type size, value_type init) { 00557 resize_internal (size, init, true); 00558 } 00559 BOOST_UBLAS_INLINE 00560 void resize (size_type size, pointer data) { 00561 resize_internal (size, data, value_type (), false); 00562 } 00563 BOOST_UBLAS_INLINE 00564 void resize (size_type size, pointer data, value_type init) { 00565 resize_internal (size, data, init, true); 00566 } 00567 00568 BOOST_UBLAS_INLINE 00569 size_type size () const { 00570 return size_; 00571 } 00572 00573 // Element access 00574 BOOST_UBLAS_INLINE 00575 const_reference operator [] (size_type i) const { 00576 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 00577 return data_ [i]; 00578 } 00579 BOOST_UBLAS_INLINE 00580 reference operator [] (size_type i) { 00581 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 00582 return data_ [i]; 00583 } 00584 00585 // Assignment 00586 BOOST_UBLAS_INLINE 00587 array_adaptor &operator = (const array_adaptor &a) { 00588 if (this != &a) { 00589 resize (a.size_); 00590 std::copy (a.data_, a.data_ + a.size_, data_); 00591 } 00592 return *this; 00593 } 00594 BOOST_UBLAS_INLINE 00595 array_adaptor &assign_temporary (array_adaptor &a) { 00596 if (own_ && a.own_) 00597 swap (a); 00598 else 00599 *this = a; 00600 return *this; 00601 } 00602 00603 // Swapping 00604 BOOST_UBLAS_INLINE 00605 void swap (array_adaptor &a) { 00606 if (this != &a) { 00607 std::swap (size_, a.size_); 00608 std::swap (own_, a.own_); 00609 std::swap (data_, a.data_); 00610 } 00611 } 00612 BOOST_UBLAS_INLINE 00613 friend void swap (array_adaptor &a1, array_adaptor &a2) { 00614 a1.swap (a2); 00615 } 00616 00617 // Iterators simply are pointers. 00618 00619 typedef const_pointer const_iterator; 00620 00621 BOOST_UBLAS_INLINE 00622 const_iterator begin () const { 00623 return data_; 00624 } 00625 BOOST_UBLAS_INLINE 00626 const_iterator end () const { 00627 return data_ + size_; 00628 } 00629 00630 typedef pointer iterator; 00631 00632 BOOST_UBLAS_INLINE 00633 iterator begin () { 00634 return data_; 00635 } 00636 BOOST_UBLAS_INLINE 00637 iterator end () { 00638 return data_ + size_; 00639 } 00640 00641 // Reverse iterators 00642 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00643 typedef std::reverse_iterator<iterator> reverse_iterator; 00644 00645 BOOST_UBLAS_INLINE 00646 const_reverse_iterator rbegin () const { 00647 return const_reverse_iterator (end ()); 00648 } 00649 BOOST_UBLAS_INLINE 00650 const_reverse_iterator rend () const { 00651 return const_reverse_iterator (begin ()); 00652 } 00653 BOOST_UBLAS_INLINE 00654 reverse_iterator rbegin () { 00655 return reverse_iterator (end ()); 00656 } 00657 BOOST_UBLAS_INLINE 00658 reverse_iterator rend () { 00659 return reverse_iterator (begin ()); 00660 } 00661 00662 private: 00663 size_type size_; 00664 bool own_; 00665 pointer data_; 00666 }; 00667 00668 #ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR 00669 // Array adaptor with shallow (reference) copy semantics of elements. 00670 // shared_array is used to maintain reference counts. 00671 // This class breaks the normal copy semantics for a storage container and is very dangerous! 00672 template<class T> 00673 class shallow_array_adaptor: 00674 public storage_array<shallow_array_adaptor<T> > { 00675 00676 typedef shallow_array_adaptor<T> self_type; 00677 00678 template<class TT> 00679 struct leaker { 00680 typedef void result_type; 00681 typedef TT *argument_type; 00682 00683 BOOST_UBLAS_INLINE 00684 result_type operator () (argument_type x) {} 00685 }; 00686 00687 public: 00688 typedef std::size_t size_type; 00689 typedef std::ptrdiff_t difference_type; 00690 typedef T value_type; 00691 typedef const T &const_reference; 00692 typedef T &reference; 00693 typedef const T *const_pointer; 00694 typedef T *pointer; 00695 00696 // Construction and destruction 00697 BOOST_UBLAS_INLINE 00698 shallow_array_adaptor (): 00699 size_ (0), own_ (true), data_ (new value_type [0]) { 00700 } 00701 explicit BOOST_UBLAS_INLINE 00702 shallow_array_adaptor (size_type size): 00703 size_ (size), own_ (true), data_ (new value_type [size]) { 00704 } 00705 BOOST_UBLAS_INLINE 00706 shallow_array_adaptor (size_type size, const value_type &init): 00707 size_ (size), own_ (true), data_ (new value_type [size]) { 00708 std::fill (data_.get (), data_.get () + size_, init); 00709 } 00710 BOOST_UBLAS_INLINE 00711 shallow_array_adaptor (size_type size, pointer data): 00712 size_ (size), own_ (false), data_ (data, leaker<value_type> ()) {} 00713 00714 BOOST_UBLAS_INLINE 00715 shallow_array_adaptor (const shallow_array_adaptor &a): 00716 storage_array<self_type> (), 00717 size_ (a.size_), own_ (a.own_), data_ (a.data_) {} 00718 00719 BOOST_UBLAS_INLINE 00720 ~shallow_array_adaptor () { 00721 } 00722 00723 // Resizing 00724 private: 00725 BOOST_UBLAS_INLINE 00726 void resize_internal (size_type size, value_type init, bool preserve = true) { 00727 if (size != size_) { 00728 shared_array<value_type> data (new value_type [size]); 00729 if (preserve) { 00730 std::copy (data_.get (), data_.get () + (std::min) (size, size_), data.get ()); 00731 std::fill (data.get () + (std::min) (size, size_), data.get () + size, init); 00732 } 00733 size_ = size; 00734 data_ = data; 00735 } 00736 } 00737 BOOST_UBLAS_INLINE 00738 void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) { 00739 if (preserve) { 00740 std::copy (data_.get (), data_.get () + (std::min) (size, size_), data); 00741 std::fill (data + (std::min) (size, size_), data + size, init); 00742 } 00743 size_ = size; 00744 data_ = data; 00745 } 00746 public: 00747 BOOST_UBLAS_INLINE 00748 void resize (size_type size) { 00749 resize_internal (size, value_type (), false); 00750 } 00751 BOOST_UBLAS_INLINE 00752 void resize (size_type size, value_type init) { 00753 resize_internal (size, init, true); 00754 } 00755 BOOST_UBLAS_INLINE 00756 void resize (size_type size, pointer data) { 00757 resize_internal (size, data, value_type (), false); 00758 } 00759 BOOST_UBLAS_INLINE 00760 void resize (size_type size, pointer data, value_type init) { 00761 resize_internal (size, data, init, true); 00762 } 00763 00764 BOOST_UBLAS_INLINE 00765 size_type size () const { 00766 return size_; 00767 } 00768 00769 // Element access 00770 BOOST_UBLAS_INLINE 00771 const_reference operator [] (size_type i) const { 00772 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 00773 return data_ [i]; 00774 } 00775 BOOST_UBLAS_INLINE 00776 reference operator [] (size_type i) { 00777 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 00778 return data_ [i]; 00779 } 00780 00781 // Assignment 00782 BOOST_UBLAS_INLINE 00783 shallow_array_adaptor &operator = (const shallow_array_adaptor &a) { 00784 if (this != &a) { 00785 resize (a.size_); 00786 std::copy (a.data_.get (), a.data_.get () + a.size_, data_.get ()); 00787 } 00788 return *this; 00789 } 00790 BOOST_UBLAS_INLINE 00791 shallow_array_adaptor &assign_temporary (shallow_array_adaptor &a) { 00792 if (own_ && a.own_) 00793 swap (a); 00794 else 00795 *this = a; 00796 return *this; 00797 } 00798 00799 // Swapping 00800 BOOST_UBLAS_INLINE 00801 void swap (shallow_array_adaptor &a) { 00802 if (this != &a) { 00803 std::swap (size_, a.size_); 00804 std::swap (own_, a.own_); 00805 std::swap (data_, a.data_); 00806 } 00807 } 00808 BOOST_UBLAS_INLINE 00809 friend void swap (shallow_array_adaptor &a1, shallow_array_adaptor &a2) { 00810 a1.swap (a2); 00811 } 00812 00813 // Iterators simply are pointers. 00814 00815 typedef const_pointer const_iterator; 00816 00817 BOOST_UBLAS_INLINE 00818 const_iterator begin () const { 00819 return data_.get (); 00820 } 00821 BOOST_UBLAS_INLINE 00822 const_iterator end () const { 00823 return data_.get () + size_; 00824 } 00825 00826 typedef pointer iterator; 00827 00828 BOOST_UBLAS_INLINE 00829 iterator begin () { 00830 return data_.get (); 00831 } 00832 BOOST_UBLAS_INLINE 00833 iterator end () { 00834 return data_.get () + size_; 00835 } 00836 00837 // Reverse iterators 00838 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00839 typedef std::reverse_iterator<iterator> reverse_iterator; 00840 00841 BOOST_UBLAS_INLINE 00842 const_reverse_iterator rbegin () const { 00843 return const_reverse_iterator (end ()); 00844 } 00845 BOOST_UBLAS_INLINE 00846 const_reverse_iterator rend () const { 00847 return const_reverse_iterator (begin ()); 00848 } 00849 BOOST_UBLAS_INLINE 00850 reverse_iterator rbegin () { 00851 return reverse_iterator (end ()); 00852 } 00853 BOOST_UBLAS_INLINE 00854 reverse_iterator rend () { 00855 return reverse_iterator (begin ()); 00856 } 00857 00858 private: 00859 size_type size_; 00860 bool own_; 00861 shared_array<value_type> data_; 00862 }; 00863 00864 #endif 00865 00866 00867 // Range class 00868 template <class Z, class D> 00869 class basic_range { 00870 typedef basic_range<Z, D> self_type; 00871 public: 00872 typedef Z size_type; 00873 typedef D difference_type; 00874 typedef size_type value_type; 00875 typedef value_type const_reference; 00876 typedef const_reference reference; 00877 typedef const value_type *const_pointer; 00878 typedef value_type *pointer; 00879 00880 // Construction and destruction 00881 BOOST_UBLAS_INLINE 00882 basic_range (): 00883 start_ (0), size_ (0) {} 00884 BOOST_UBLAS_INLINE 00885 basic_range (size_type start, size_type stop): 00886 start_ (start), size_ (stop - start) { 00887 BOOST_UBLAS_CHECK (start_ <= stop, bad_index ()); 00888 } 00889 00890 BOOST_UBLAS_INLINE 00891 size_type start () const { 00892 return start_; 00893 } 00894 BOOST_UBLAS_INLINE 00895 size_type size () const { 00896 return size_; 00897 } 00898 00899 // Random Access Container 00900 BOOST_UBLAS_INLINE 00901 size_type max_size () const { 00902 return size_; 00903 } 00904 00905 BOOST_UBLAS_INLINE 00906 bool empty () const { 00907 return size_ == 0; 00908 } 00909 00910 // Element access 00911 BOOST_UBLAS_INLINE 00912 const_reference operator () (size_type i) const { 00913 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 00914 return start_ + i; 00915 } 00916 00917 // Composition 00918 BOOST_UBLAS_INLINE 00919 basic_range compose (const basic_range &r) const { 00920 return basic_range (start_ + r.start_, start_ + r.start_ + r.size_); 00921 } 00922 00923 // Comparison 00924 BOOST_UBLAS_INLINE 00925 bool operator == (const basic_range &r) const { 00926 return start_ == r.start_ && size_ == r.size_; 00927 } 00928 BOOST_UBLAS_INLINE 00929 bool operator != (const basic_range &r) const { 00930 return ! (*this == r); 00931 } 00932 00933 // Iterator types 00934 private: 00935 // Use and index 00936 typedef size_type const_subiterator_type; 00937 00938 public: 00939 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 00940 typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator; 00941 #else 00942 class const_iterator: 00943 public container_const_reference<basic_range>, 00944 public random_access_iterator_base<std::random_access_iterator_tag, 00945 const_iterator, value_type> { 00946 public: 00947 typedef typename basic_range::value_type value_type; 00948 typedef typename basic_range::difference_type difference_type; 00949 typedef typename basic_range::const_reference reference; 00950 typedef typename basic_range::const_pointer pointer; 00951 00952 // Construction and destruction 00953 BOOST_UBLAS_INLINE 00954 const_iterator (): 00955 container_const_reference<basic_range> (), it_ () {} 00956 BOOST_UBLAS_INLINE 00957 const_iterator (const basic_range &r, const const_subiterator_type &it): 00958 container_const_reference<basic_range> (r), it_ (it) {} 00959 00960 // Arithmetic 00961 BOOST_UBLAS_INLINE 00962 const_iterator &operator ++ () { 00963 ++ it_; 00964 return *this; 00965 } 00966 BOOST_UBLAS_INLINE 00967 const_iterator &operator -- () { 00968 BOOST_UBLAS_CHECK (it_ > 0, bad_index ()); 00969 -- it_; 00970 return *this; 00971 } 00972 BOOST_UBLAS_INLINE 00973 const_iterator &operator += (difference_type n) { 00974 BOOST_UBLAS_CHECK (n >= 0 || it_ >= size_type(-n), bad_index ()); 00975 it_ += n; 00976 return *this; 00977 } 00978 BOOST_UBLAS_INLINE 00979 const_iterator &operator -= (difference_type n) { 00980 BOOST_UBLAS_CHECK (n <= 0 || it_ >= size_type(n), bad_index ()); 00981 it_ -= n; 00982 return *this; 00983 } 00984 BOOST_UBLAS_INLINE 00985 difference_type operator - (const const_iterator &it) const { 00986 return it_ - it.it_; 00987 } 00988 00989 // Dereference 00990 BOOST_UBLAS_INLINE 00991 const_reference operator * () const { 00992 BOOST_UBLAS_CHECK ((*this) ().start () <= it_, bad_index ()); 00993 BOOST_UBLAS_CHECK (it_ < (*this) ().start () + (*this) ().size (), bad_index ()); 00994 return it_; 00995 } 00996 00997 BOOST_UBLAS_INLINE 00998 const_reference operator [] (difference_type n) const { 00999 return *(*this + n); 01000 } 01001 01002 // Index 01003 BOOST_UBLAS_INLINE 01004 size_type index () const { 01005 BOOST_UBLAS_CHECK ((*this) ().start () <= it_, bad_index ()); 01006 BOOST_UBLAS_CHECK (it_ < (*this) ().start () + (*this) ().size (), bad_index ()); 01007 return it_ - (*this) ().start (); 01008 } 01009 01010 // Assignment 01011 BOOST_UBLAS_INLINE 01012 const_iterator &operator = (const const_iterator &it) { 01013 // Comeau recommends... 01014 this->assign (&it ()); 01015 it_ = it.it_; 01016 return *this; 01017 } 01018 01019 // Comparison 01020 BOOST_UBLAS_INLINE 01021 bool operator == (const const_iterator &it) const { 01022 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 01023 return it_ == it.it_; 01024 } 01025 BOOST_UBLAS_INLINE 01026 bool operator < (const const_iterator &it) const { 01027 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 01028 return it_ < it.it_; 01029 } 01030 01031 private: 01032 const_subiterator_type it_; 01033 }; 01034 #endif 01035 01036 BOOST_UBLAS_INLINE 01037 const_iterator begin () const { 01038 return const_iterator (*this, start_); 01039 } 01040 BOOST_UBLAS_INLINE 01041 const_iterator end () const { 01042 return const_iterator (*this, start_ + size_); 01043 } 01044 01045 // Reverse iterator 01046 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 01047 01048 BOOST_UBLAS_INLINE 01049 const_reverse_iterator rbegin () const { 01050 return const_reverse_iterator (end ()); 01051 } 01052 BOOST_UBLAS_INLINE 01053 const_reverse_iterator rend () const { 01054 return const_reverse_iterator (begin ()); 01055 } 01056 01057 BOOST_UBLAS_INLINE 01058 basic_range preprocess (size_type size) const { 01059 if (this != &all_) 01060 return *this; 01061 return basic_range (0, size); 01062 } 01063 static 01064 BOOST_UBLAS_INLINE 01065 const basic_range &all () { 01066 return all_; 01067 } 01068 01069 private: 01070 size_type start_; 01071 size_type size_; 01072 static const basic_range all_; 01073 }; 01074 01075 template <class Z, class D> 01076 const basic_range<Z,D> basic_range<Z,D>::all_ (0, size_type (-1)); 01077 01078 01079 // Slice class 01080 template <class Z, class D> 01081 class basic_slice { 01082 typedef basic_slice<Z, D> self_type; 01083 public: 01084 typedef Z size_type; 01085 typedef D difference_type; 01086 typedef size_type value_type; 01087 typedef value_type const_reference; 01088 typedef const_reference reference; 01089 typedef const value_type *const_pointer; 01090 typedef value_type *pointer; 01091 01092 // Construction and destruction 01093 BOOST_UBLAS_INLINE 01094 basic_slice (): 01095 start_ (0), stride_ (0), size_ (0) {} 01096 BOOST_UBLAS_INLINE 01097 basic_slice (size_type start, difference_type stride, size_type size): 01098 start_ (start), stride_ (stride), size_ (size) {} 01099 01100 BOOST_UBLAS_INLINE 01101 size_type start () const { 01102 return start_; 01103 } 01104 BOOST_UBLAS_INLINE 01105 difference_type stride () const { 01106 return stride_; 01107 } 01108 BOOST_UBLAS_INLINE 01109 size_type size () const { 01110 return size_; 01111 } 01112 01113 // Random Access Container 01114 BOOST_UBLAS_INLINE 01115 size_type max_size () const { 01116 return size_; 01117 } 01118 01119 BOOST_UBLAS_INLINE 01120 bool empty () const { 01121 return size_ == 0; 01122 } 01123 01124 // Element access 01125 BOOST_UBLAS_INLINE 01126 const_reference operator () (size_type i) const { 01127 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 01128 BOOST_UBLAS_CHECK (stride_ >= 0 || start_ >= i * -stride_, bad_index ()); 01129 return start_ + i * stride_; 01130 } 01131 01132 // Composition 01133 BOOST_UBLAS_INLINE 01134 basic_slice compose (const basic_range<size_type, difference_type> &r) const { 01135 BOOST_UBLAS_CHECK (stride_ >=0 || start_ >= -stride_ * r.start(), bad_index ()); 01136 return basic_slice (start_ + stride_ * r.start (), stride_, r.size ()); 01137 } 01138 BOOST_UBLAS_INLINE 01139 basic_slice compose (const basic_slice &s) const { 01140 BOOST_UBLAS_CHECK (stride_ >=0 || start_ >= -stride_ * s.start_, bad_index ()); 01141 return basic_slice (start_ + stride_ * s.start_, stride_ * s.stride_, s.size_); 01142 } 01143 01144 // Comparison 01145 BOOST_UBLAS_INLINE 01146 bool operator == (const basic_slice &s) const { 01147 return start_ == s.start_ && stride_ == s.stride_ && size_ == s.size_; 01148 } 01149 BOOST_UBLAS_INLINE 01150 bool operator != (const basic_slice &s) const { 01151 return ! (*this == s); 01152 } 01153 01154 // Iterator types 01155 private: 01156 // Use and index 01157 typedef size_type const_subiterator_type; 01158 01159 public: 01160 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 01161 typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator; 01162 #else 01163 class const_iterator: 01164 public container_const_reference<basic_slice>, 01165 public random_access_iterator_base<std::random_access_iterator_tag, 01166 const_iterator, value_type> { 01167 public: 01168 typedef typename basic_slice::value_type value_type; 01169 typedef typename basic_slice::difference_type difference_type; 01170 typedef typename basic_slice::const_reference reference; 01171 typedef typename basic_slice::const_pointer pointer; 01172 01173 // Construction and destruction 01174 BOOST_UBLAS_INLINE 01175 const_iterator (): 01176 container_const_reference<basic_slice> (), it_ () {} 01177 BOOST_UBLAS_INLINE 01178 const_iterator (const basic_slice &s, const const_subiterator_type &it): 01179 container_const_reference<basic_slice> (s), it_ (it) {} 01180 01181 // Arithmetic 01182 BOOST_UBLAS_INLINE 01183 const_iterator &operator ++ () { 01184 ++it_; 01185 return *this; 01186 } 01187 BOOST_UBLAS_INLINE 01188 const_iterator &operator -- () { 01189 BOOST_UBLAS_CHECK (it_ > 0, bad_index ()); 01190 --it_; 01191 return *this; 01192 } 01193 BOOST_UBLAS_INLINE 01194 const_iterator &operator += (difference_type n) { 01195 BOOST_UBLAS_CHECK (n >= 0 || it_ >= size_type(-n), bad_index ()); 01196 it_ += n; 01197 return *this; 01198 } 01199 BOOST_UBLAS_INLINE 01200 const_iterator &operator -= (difference_type n) { 01201 BOOST_UBLAS_CHECK (n <= 0 || it_ >= size_type(n), bad_index ()); 01202 it_ -= n; 01203 return *this; 01204 } 01205 BOOST_UBLAS_INLINE 01206 difference_type operator - (const const_iterator &it) const { 01207 return it_ - it.it_; 01208 } 01209 01210 // Dereference 01211 BOOST_UBLAS_INLINE 01212 const_reference operator * () const { 01213 BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ()); 01214 return (*this) ().start () + it_* (*this) ().stride (); 01215 } 01216 01217 BOOST_UBLAS_INLINE 01218 const_reference operator [] (difference_type n) const { 01219 return *(*this + n); 01220 } 01221 01222 // Index 01223 BOOST_UBLAS_INLINE 01224 size_type index () const { 01225 BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ()); 01226 return it_; 01227 } 01228 01229 // Assignment 01230 BOOST_UBLAS_INLINE 01231 const_iterator &operator = (const const_iterator &it) { 01232 // Comeau recommends... 01233 this->assign (&it ()); 01234 it_ = it.it_; 01235 return *this; 01236 } 01237 01238 // Comparison 01239 BOOST_UBLAS_INLINE 01240 bool operator == (const const_iterator &it) const { 01241 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 01242 return it_ == it.it_; 01243 } 01244 BOOST_UBLAS_INLINE 01245 bool operator < (const const_iterator &it) const { 01246 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 01247 return it_ < it.it_; 01248 } 01249 01250 private: 01251 const_subiterator_type it_; 01252 }; 01253 #endif 01254 01255 BOOST_UBLAS_INLINE 01256 const_iterator begin () const { 01257 return const_iterator (*this, 0); 01258 } 01259 BOOST_UBLAS_INLINE 01260 const_iterator end () const { 01261 return const_iterator (*this, size_); 01262 } 01263 01264 // Reverse iterator 01265 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 01266 01267 BOOST_UBLAS_INLINE 01268 const_reverse_iterator rbegin () const { 01269 return const_reverse_iterator (end ()); 01270 } 01271 BOOST_UBLAS_INLINE 01272 const_reverse_iterator rend () const { 01273 return const_reverse_iterator (begin ()); 01274 } 01275 01276 BOOST_UBLAS_INLINE 01277 basic_slice preprocess (size_type size) const { 01278 if (this != &all_) 01279 return *this; 01280 return basic_slice (0, 1, size); 01281 } 01282 static 01283 BOOST_UBLAS_INLINE 01284 const basic_slice &all () { 01285 return all_; 01286 } 01287 01288 private: 01289 size_type start_; 01290 difference_type stride_; 01291 size_type size_; 01292 static const basic_slice all_; 01293 }; 01294 01295 template <class Z, class D> 01296 const basic_slice<Z,D> basic_slice<Z,D>::all_ (0, 1, size_type (-1)); 01297 01298 01299 // Indirect array class 01300 template<class A> 01301 class indirect_array { 01302 typedef indirect_array<A> self_type; 01303 public: 01304 typedef A array_type; 01305 typedef const A const_array_type; 01306 typedef typename A::size_type size_type; 01307 typedef typename A::difference_type difference_type; 01308 typedef typename A::value_type value_type; 01309 typedef typename A::const_reference const_reference; 01310 typedef typename A::reference reference; 01311 typedef typename A::const_pointer const_pointer; 01312 typedef typename A::pointer pointer; 01313 01314 // Construction and destruction 01315 BOOST_UBLAS_INLINE 01316 indirect_array (): 01317 size_ (), data_ () {} 01318 explicit BOOST_UBLAS_INLINE 01319 indirect_array (size_type size): 01320 size_ (size), data_ (size) {} 01321 BOOST_UBLAS_INLINE 01322 indirect_array (size_type size, const array_type &data): 01323 size_ (size), data_ (data) {} 01324 BOOST_UBLAS_INLINE 01325 indirect_array (pointer start, pointer stop): 01326 size_ (stop - start), data_ (stop - start) { 01327 std::copy (start, stop, data_.begin ()); 01328 } 01329 01330 BOOST_UBLAS_INLINE 01331 size_type size () const { 01332 return size_; 01333 } 01334 BOOST_UBLAS_INLINE 01335 const_array_type data () const { 01336 return data_; 01337 } 01338 BOOST_UBLAS_INLINE 01339 array_type data () { 01340 return data_; 01341 } 01342 01343 // Random Access Container 01344 BOOST_UBLAS_INLINE 01345 size_type max_size () const { 01346 return size_; 01347 } 01348 01349 BOOST_UBLAS_INLINE 01350 bool empty () const { 01351 return data_.size () == 0; 01352 } 01353 01354 // Element access 01355 BOOST_UBLAS_INLINE 01356 const_reference operator () (size_type i) const { 01357 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 01358 return data_ [i]; 01359 } 01360 BOOST_UBLAS_INLINE 01361 reference operator () (size_type i) { 01362 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 01363 return data_ [i]; 01364 } 01365 01366 BOOST_UBLAS_INLINE 01367 const_reference operator [] (size_type i) const { 01368 return (*this) (i); 01369 } 01370 BOOST_UBLAS_INLINE 01371 reference operator [] (size_type i) { 01372 return (*this) (i); 01373 } 01374 01375 // Composition 01376 BOOST_UBLAS_INLINE 01377 indirect_array compose (const basic_range<size_type, difference_type> &r) const { 01378 BOOST_UBLAS_CHECK (r.start () + r.size () <= size_, bad_size ()); 01379 array_type data (r.size ()); 01380 for (size_type i = 0; i < r.size (); ++ i) 01381 data [i] = data_ [r.start () + i]; 01382 return indirect_array (r.size (), data); 01383 } 01384 BOOST_UBLAS_INLINE 01385 indirect_array compose (const basic_slice<size_type, difference_type> &s) const { 01386 BOOST_UBLAS_CHECK (s.start () + s.stride () * (s.size () - (s.size () > 0)) <= size (), bad_size ()); 01387 array_type data (s.size ()); 01388 for (size_type i = 0; i < s.size (); ++ i) 01389 data [i] = data_ [s.start () + s.stride () * i]; 01390 return indirect_array (s.size (), data); 01391 } 01392 BOOST_UBLAS_INLINE 01393 indirect_array compose (const indirect_array &ia) const { 01394 array_type data (ia.size_); 01395 for (size_type i = 0; i < ia.size_; ++ i) { 01396 BOOST_UBLAS_CHECK (ia.data_ [i] <= size_, bad_size ()); 01397 data [i] = data_ [ia.data_ [i]]; 01398 } 01399 return indirect_array (ia.size_, data); 01400 } 01401 01402 // Comparison 01403 template<class OA> 01404 BOOST_UBLAS_INLINE 01405 bool operator == (const indirect_array<OA> &ia) const { 01406 if (size_ != ia.size_) 01407 return false; 01408 for (size_type i = 0; i < BOOST_UBLAS_SAME (size_, ia.size_); ++ i) 01409 if (data_ [i] != ia.data_ [i]) 01410 return false; 01411 return true; 01412 } 01413 template<class OA> 01414 BOOST_UBLAS_INLINE 01415 bool operator != (const indirect_array<OA> &ia) const { 01416 return ! (*this == ia); 01417 } 01418 01419 // Iterator types 01420 private: 01421 // Use a index difference 01422 typedef difference_type const_subiterator_type; 01423 01424 public: 01425 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 01426 typedef indexed_const_iterator<indirect_array, std::random_access_iterator_tag> const_iterator; 01427 #else 01428 class const_iterator: 01429 public container_const_reference<indirect_array>, 01430 public random_access_iterator_base<std::random_access_iterator_tag, 01431 const_iterator, value_type> { 01432 public: 01433 typedef typename indirect_array::value_type value_type; 01434 typedef typename indirect_array::difference_type difference_type; 01435 typedef typename indirect_array::const_reference reference; 01436 typedef typename indirect_array::const_pointer pointer; 01437 01438 // Construction and destruction 01439 BOOST_UBLAS_INLINE 01440 const_iterator (): 01441 container_const_reference<indirect_array> (), it_ () {} 01442 BOOST_UBLAS_INLINE 01443 const_iterator (const indirect_array &ia, const const_subiterator_type &it): 01444 container_const_reference<indirect_array> (ia), it_ (it) {} 01445 01446 // Arithmetic 01447 BOOST_UBLAS_INLINE 01448 const_iterator &operator ++ () { 01449 ++ it_; 01450 return *this; 01451 } 01452 BOOST_UBLAS_INLINE 01453 const_iterator &operator -- () { 01454 -- it_; 01455 return *this; 01456 } 01457 BOOST_UBLAS_INLINE 01458 const_iterator &operator += (difference_type n) { 01459 it_ += n; 01460 return *this; 01461 } 01462 BOOST_UBLAS_INLINE 01463 const_iterator &operator -= (difference_type n) { 01464 it_ -= n; 01465 return *this; 01466 } 01467 BOOST_UBLAS_INLINE 01468 difference_type operator - (const const_iterator &it) const { 01469 return it_ - it.it_; 01470 } 01471 01472 // Dereference 01473 BOOST_UBLAS_INLINE 01474 const_reference operator * () const { 01475 return (*this) () (it_); 01476 } 01477 01478 BOOST_UBLAS_INLINE 01479 const_reference operator [] (difference_type n) const { 01480 return *(*this + n); 01481 } 01482 01483 // Index 01484 BOOST_UBLAS_INLINE 01485 size_type index () const { 01486 return it_; 01487 } 01488 01489 // Assignment 01490 BOOST_UBLAS_INLINE 01491 const_iterator &operator = (const const_iterator &it) { 01492 // Comeau recommends... 01493 this->assign (&it ()); 01494 it_ = it.it_; 01495 return *this; 01496 } 01497 01498 // Comparison 01499 BOOST_UBLAS_INLINE 01500 bool operator == (const const_iterator &it) const { 01501 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 01502 return it_ == it.it_; 01503 } 01504 BOOST_UBLAS_INLINE 01505 bool operator < (const const_iterator &it) const { 01506 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ()); 01507 return it_ < it.it_; 01508 } 01509 01510 private: 01511 const_subiterator_type it_; 01512 }; 01513 #endif 01514 01515 BOOST_UBLAS_INLINE 01516 const_iterator begin () const { 01517 return const_iterator (*this, 0); 01518 } 01519 BOOST_UBLAS_INLINE 01520 const_iterator end () const { 01521 return const_iterator (*this, size_); 01522 } 01523 01524 // Reverse iterator 01525 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 01526 01527 BOOST_UBLAS_INLINE 01528 const_reverse_iterator rbegin () const { 01529 return const_reverse_iterator (end ()); 01530 } 01531 BOOST_UBLAS_INLINE 01532 const_reverse_iterator rend () const { 01533 return const_reverse_iterator (begin ()); 01534 } 01535 01536 BOOST_UBLAS_INLINE 01537 indirect_array preprocess (size_type size) const { 01538 if (this != &all_) 01539 return *this; 01540 indirect_array ia (size); 01541 for (size_type i = 0; i < size; ++ i) 01542 ia (i) = i; 01543 return ia; 01544 } 01545 static 01546 BOOST_UBLAS_INLINE 01547 const indirect_array &all () { 01548 return all_; 01549 } 01550 01551 private: 01552 size_type size_; 01553 array_type data_; 01554 static const indirect_array all_; 01555 }; 01556 01557 template<class A> 01558 const indirect_array<A> indirect_array<A>::all_; 01559 01560 01561 01562 // Gunter Winkler contributed the classes index_pair, index_pair_array, 01563 // index_triple and index_triple_array to enable inplace sort of parallel arrays. 01564 01565 template <class V> 01566 class index_pair : 01567 private boost::noncopyable, 01568 public container_reference<V> { 01569 01570 typedef index_pair<V> self_type; 01571 public: 01572 typedef typename V::size_type size_type; 01573 01574 BOOST_UBLAS_INLINE 01575 index_pair(V& v, size_type i) : 01576 container_reference<V>(v), i_(i), 01577 v1_(v.data1_[i]), v2_(v.data2_[i]), 01578 dirty_(false), is_copy_(false) {} 01579 BOOST_UBLAS_INLINE 01580 index_pair(const self_type& rhs) : 01581 container_reference<V>(rhs()), i_(0), 01582 v1_(rhs.v1_), v2_(rhs.v2_), 01583 dirty_(false), is_copy_(true) {} 01584 BOOST_UBLAS_INLINE 01585 ~index_pair() { 01586 if (dirty_ && (!is_copy_) ) { 01587 (*this)().data1_[i_] = v1_; 01588 (*this)().data2_[i_] = v2_; 01589 } 01590 } 01591 01592 BOOST_UBLAS_INLINE 01593 self_type& operator=(const self_type& rhs) { 01594 v1_ = rhs.v1_; 01595 v2_ = rhs.v2_; 01596 dirty_ = true; 01597 return *this; 01598 } 01599 01600 BOOST_UBLAS_INLINE 01601 void swap(self_type& rhs) { 01602 self_type tmp(rhs); 01603 rhs = *this; 01604 *this = tmp; 01605 } 01606 BOOST_UBLAS_INLINE 01607 friend void swap(self_type& lhs, self_type& rhs) { 01608 lhs.swap(rhs); 01609 } 01610 01611 BOOST_UBLAS_INLINE 01612 bool equal(const self_type& rhs) const { 01613 return (v1_ == rhs.v1_); 01614 } 01615 BOOST_UBLAS_INLINE 01616 bool less(const self_type& rhs) const { 01617 return (v1_ < rhs.v1_); 01618 } 01619 BOOST_UBLAS_INLINE 01620 friend bool operator == (const self_type& lhs, const self_type& rhs) { 01621 return lhs.equal(rhs); 01622 } 01623 BOOST_UBLAS_INLINE 01624 friend bool operator != (const self_type& lhs, const self_type& rhs) { 01625 return !lhs.equal(rhs); 01626 } 01627 BOOST_UBLAS_INLINE 01628 friend bool operator < (const self_type& lhs, const self_type& rhs) { 01629 return lhs.less(rhs); 01630 } 01631 BOOST_UBLAS_INLINE 01632 friend bool operator >= (const self_type& lhs, const self_type& rhs) { 01633 return !lhs.less(rhs); 01634 } 01635 BOOST_UBLAS_INLINE 01636 friend bool operator > (const self_type& lhs, const self_type& rhs) { 01637 return rhs.less(lhs); 01638 } 01639 BOOST_UBLAS_INLINE 01640 friend bool operator <= (const self_type& lhs, const self_type& rhs) { 01641 return !rhs.less(lhs); 01642 } 01643 01644 private: 01645 size_type i_; 01646 typename V::value1_type v1_; 01647 typename V::value2_type v2_; 01648 bool dirty_; 01649 bool is_copy_; 01650 }; 01651 01652 template <class V1, class V2> 01653 class index_pair_array: 01654 private boost::noncopyable { 01655 01656 typedef index_pair_array<V1, V2> self_type; 01657 public: 01658 typedef typename V1::value_type value1_type; 01659 typedef typename V2::value_type value2_type; 01660 01661 typedef typename V1::size_type size_type; 01662 typedef typename V1::difference_type difference_type; 01663 typedef index_pair<self_type> value_type; 01664 // There is nothing that can be referenced directly. Always return a copy of the index_pair 01665 typedef value_type reference; 01666 typedef const value_type const_reference; 01667 01668 BOOST_UBLAS_INLINE 01669 index_pair_array(size_type size, V1& data1, V2& data2) : 01670 size_(size),data1_(data1),data2_(data2) {} 01671 01672 BOOST_UBLAS_INLINE 01673 size_type size() const { 01674 return size_; 01675 } 01676 01677 BOOST_UBLAS_INLINE 01678 const_reference operator () (size_type i) const { 01679 return value_type((*this), i); 01680 } 01681 BOOST_UBLAS_INLINE 01682 reference operator () (size_type i) { 01683 return value_type((*this), i); 01684 } 01685 01686 typedef indexed_iterator<self_type, std::random_access_iterator_tag> iterator; 01687 typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator; 01688 01689 BOOST_UBLAS_INLINE 01690 iterator begin() { 01691 return iterator( (*this), 0); 01692 } 01693 BOOST_UBLAS_INLINE 01694 iterator end() { 01695 return iterator( (*this), size()); 01696 } 01697 01698 BOOST_UBLAS_INLINE 01699 const_iterator begin() const { 01700 return const_iterator( (*this), 0); 01701 } 01702 BOOST_UBLAS_INLINE 01703 const_iterator end() const { 01704 return const_iterator( (*this), size()); 01705 } 01706 01707 // unnecessary function: 01708 BOOST_UBLAS_INLINE 01709 bool equal(size_type i1, size_type i2) const { 01710 return data1_[i1] == data1_[i2]; 01711 } 01712 BOOST_UBLAS_INLINE 01713 bool less(size_type i1, size_type i2) const { 01714 return data1_[i1] < data1_[i2]; 01715 } 01716 01717 // gives a large speedup 01718 BOOST_UBLAS_INLINE 01719 friend void iter_swap(const iterator& lhs, const iterator& rhs) { 01720 const size_type i1 = lhs.index(); 01721 const size_type i2 = rhs.index(); 01722 std::swap(lhs().data1_[i1], rhs().data1_[i2]); 01723 std::swap(lhs().data2_[i1], rhs().data2_[i2]); 01724 } 01725 01726 private: 01727 size_type size_; 01728 V1& data1_; 01729 V2& data2_; 01730 01731 // friend class value_type; 01732 friend class index_pair<self_type>; 01733 }; 01734 01735 template <class M> 01736 class index_triple : 01737 private boost::noncopyable, 01738 public container_reference<M> { 01739 01740 typedef index_triple<M> self_type; 01741 public: 01742 typedef typename M::size_type size_type; 01743 01744 BOOST_UBLAS_INLINE 01745 index_triple(M& m, size_type i) : 01746 container_reference<M>(m), i_(i), 01747 v1_(m.data1_[i]), v2_(m.data2_[i]), v3_(m.data3_[i]), 01748 dirty_(false), is_copy_(false) {} 01749 BOOST_UBLAS_INLINE 01750 index_triple(const self_type& rhs) : 01751 container_reference<M>(rhs()), i_(0), 01752 v1_(rhs.v1_), v2_(rhs.v2_), v3_(rhs.v3_), 01753 dirty_(false), is_copy_(true) {} 01754 BOOST_UBLAS_INLINE 01755 ~index_triple() { 01756 if (dirty_ && (!is_copy_) ) { 01757 (*this)().data1_[i_] = v1_; 01758 (*this)().data2_[i_] = v2_; 01759 (*this)().data3_[i_] = v3_; 01760 } 01761 } 01762 01763 BOOST_UBLAS_INLINE 01764 self_type& operator=(const self_type& rhs) { 01765 v1_ = rhs.v1_; 01766 v2_ = rhs.v2_; 01767 v3_ = rhs.v3_; 01768 dirty_ = true; 01769 return *this; 01770 } 01771 01772 BOOST_UBLAS_INLINE 01773 void swap(self_type& rhs) { 01774 self_type tmp(rhs); 01775 rhs = *this; 01776 *this = tmp; 01777 } 01778 BOOST_UBLAS_INLINE 01779 friend void swap(self_type& lhs, self_type& rhs) { 01780 lhs.swap(rhs); 01781 } 01782 01783 BOOST_UBLAS_INLINE 01784 bool equal(const self_type& rhs) const { 01785 return ((v1_ == rhs.v1_) && (v2_ == rhs.v2_)); 01786 } 01787 BOOST_UBLAS_INLINE 01788 bool less(const self_type& rhs) const { 01789 return ((v1_ < rhs.v1_) || 01790 (v1_ == rhs.v1_ && v2_ < rhs.v2_)); 01791 } 01792 BOOST_UBLAS_INLINE 01793 friend bool operator == (const self_type& lhs, const self_type& rhs) { 01794 return lhs.equal(rhs); 01795 } 01796 BOOST_UBLAS_INLINE 01797 friend bool operator != (const self_type& lhs, const self_type& rhs) { 01798 return !lhs.equal(rhs); 01799 } 01800 BOOST_UBLAS_INLINE 01801 friend bool operator < (const self_type& lhs, const self_type& rhs) { 01802 return lhs.less(rhs); 01803 } 01804 BOOST_UBLAS_INLINE 01805 friend bool operator >= (const self_type& lhs, const self_type& rhs) { 01806 return !lhs.less(rhs); 01807 } 01808 BOOST_UBLAS_INLINE 01809 friend bool operator > (const self_type& lhs, const self_type& rhs) { 01810 return rhs.less(lhs); 01811 } 01812 BOOST_UBLAS_INLINE 01813 friend bool operator <= (const self_type& lhs, const self_type& rhs) { 01814 return !rhs.less(lhs); 01815 } 01816 01817 private: 01818 size_type i_; 01819 typename M::value1_type v1_; 01820 typename M::value2_type v2_; 01821 typename M::value3_type v3_; 01822 bool dirty_; 01823 bool is_copy_; 01824 }; 01825 01826 template <class V1, class V2, class V3> 01827 class index_triple_array: 01828 private boost::noncopyable { 01829 01830 typedef index_triple_array<V1, V2, V3> self_type; 01831 public: 01832 typedef typename V1::value_type value1_type; 01833 typedef typename V2::value_type value2_type; 01834 typedef typename V3::value_type value3_type; 01835 01836 typedef typename V1::size_type size_type; 01837 typedef typename V1::difference_type difference_type; 01838 typedef index_triple<self_type> value_type; 01839 // There is nothing that can be referenced directly. Always return a copy of the index_triple 01840 typedef value_type reference; 01841 typedef const value_type const_reference; 01842 01843 BOOST_UBLAS_INLINE 01844 index_triple_array(size_type size, V1& data1, V2& data2, V3& data3) : 01845 size_(size),data1_(data1),data2_(data2),data3_(data3) {} 01846 01847 BOOST_UBLAS_INLINE 01848 size_type size() const { 01849 return size_; 01850 } 01851 01852 BOOST_UBLAS_INLINE 01853 const_reference operator () (size_type i) const { 01854 return value_type((*this), i); 01855 } 01856 BOOST_UBLAS_INLINE 01857 reference operator () (size_type i) { 01858 return value_type((*this), i); 01859 } 01860 01861 typedef indexed_iterator<self_type, std::random_access_iterator_tag> iterator; 01862 typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator; 01863 01864 BOOST_UBLAS_INLINE 01865 iterator begin() { 01866 return iterator( (*this), 0); 01867 } 01868 BOOST_UBLAS_INLINE 01869 iterator end() { 01870 return iterator( (*this), size()); 01871 } 01872 01873 BOOST_UBLAS_INLINE 01874 const_iterator begin() const { 01875 return const_iterator( (*this), 0); 01876 } 01877 BOOST_UBLAS_INLINE 01878 const_iterator end() const { 01879 return const_iterator( (*this), size()); 01880 } 01881 01882 // unnecessary function: 01883 BOOST_UBLAS_INLINE 01884 bool equal(size_type i1, size_type i2) const { 01885 return ((data1_[i1] == data1_[i2]) && (data2_[i1] == data2_[i2])); 01886 } 01887 BOOST_UBLAS_INLINE 01888 bool less(size_type i1, size_type i2) const { 01889 return ((data1_[i1] < data1_[i2]) || 01890 (data1_[i1] == data1_[i2] && data2_[i1] < data2_[i2])); 01891 } 01892 01893 // gives a large speedup 01894 BOOST_UBLAS_INLINE 01895 friend void iter_swap(const iterator& lhs, const iterator& rhs) { 01896 const size_type i1 = lhs.index(); 01897 const size_type i2 = rhs.index(); 01898 std::swap(lhs().data1_[i1], rhs().data1_[i2]); 01899 std::swap(lhs().data2_[i1], rhs().data2_[i2]); 01900 std::swap(lhs().data3_[i1], rhs().data3_[i2]); 01901 } 01902 01903 private: 01904 size_type size_; 01905 V1& data1_; 01906 V2& data2_; 01907 V3& data3_; 01908 01909 // friend class value_type; 01910 friend class index_triple<self_type>; 01911 }; 01912 01913 }}} 01914 01915 #endif