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

Generated on Wed Oct 15 2014 00:37:23 for Jafar by doxygen 1.7.6.1
LAAS-CNRS