- Main Page
- Related Pages
- Classes
- Files

- File List

# storage.hpp

    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