Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/numeric/ublas/storage.hpp @ 30

Last change on this file since 30 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 58.4 KB
Line 
1//
2//  Copyright (c) 2000-2002
3//  Joerg Walter, Mathias Koch
4//
5//  Permission to use, copy, modify, distribute and sell this software
6//  and its documentation for any purpose is hereby granted without fee,
7//  provided that the above copyright notice appear in all copies and
8//  that both that copyright notice and this permission notice appear
9//  in supporting documentation.  The authors make no representations
10//  about the suitability of this software for any purpose.
11//  It is provided "as is" without express or implied warranty.
12//
13//  The authors gratefully acknowledge the support of
14//  GeNeSys mbH & Co. KG in producing this work.
15//
16
17#ifndef BOOST_UBLAS_STORAGE_H
18#define BOOST_UBLAS_STORAGE_H
19
20#include <algorithm>
21#ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR
22#include <boost/shared_array.hpp>
23#endif
24
25#include <boost/numeric/ublas/exception.hpp>
26#include <boost/numeric/ublas/detail/iterator.hpp>
27
28
29namespace boost { namespace numeric { namespace ublas {
30
31
32    // Base class for Storage Arrays - see the Barton Nackman trick
33    template<class E>
34    class storage_array:
35        private nonassignable {
36    };
37
38
39    // Unbounded array - with allocator
40    template<class T, class ALLOC>
41    class unbounded_array:
42        public storage_array<unbounded_array<T, ALLOC> > {
43
44        typedef unbounded_array<T, ALLOC> self_type;
45    public:
46        typedef ALLOC allocator_type;
47        typedef typename ALLOC::size_type size_type;
48        typedef typename ALLOC::difference_type difference_type;
49        typedef T value_type;
50        typedef const T &const_reference;
51        typedef T &reference;
52        typedef const T *const_pointer;
53        typedef T *pointer;
54        typedef const_pointer const_iterator;
55        typedef pointer iterator;
56
57        // Construction and destruction
58        explicit BOOST_UBLAS_INLINE
59        unbounded_array (const ALLOC &a = ALLOC()):
60            alloc_ (a), size_ (0) {
61            data_ = 0;
62        }
63        explicit BOOST_UBLAS_INLINE
64        unbounded_array (size_type size, const ALLOC &a = ALLOC()):
65            alloc_(a), size_ (size) {
66            if (size_) {
67                data_ = alloc_.allocate (size_);
68                // ISSUE some compilers may zero POD here
69#ifdef BOOST_UBLAS_USEFUL_ARRAY_PLACEMENT_NEW
70                // array form fails on some compilers due to size cookie, is it standard conforming?
71                new (data_) value_type[size_];
72#else
73                for (pointer d = data_; d != data_ + size_; ++d)
74                    new (d) value_type;
75#endif
76            }
77            else
78                data_ = 0;
79        }
80        // No value initialised, but still be default constructed
81        BOOST_UBLAS_INLINE
82        unbounded_array (size_type size, const value_type &init, const ALLOC &a = ALLOC()):
83            alloc_ (a), size_ (size) {
84            if (size_) {
85                data_ = alloc_.allocate (size_);
86                std::uninitialized_fill (begin(), end(), init);
87            }
88            else
89                data_ = 0;
90        }
91        BOOST_UBLAS_INLINE
92        unbounded_array (const unbounded_array &c):
93            alloc_ (c.alloc_), size_ (c.size_) {
94            if (size_) {
95                data_ = alloc_.allocate (size_);
96                std::uninitialized_copy (c.begin(), c.end(), begin());
97            }
98            else
99                data_ = 0;
100        }
101        BOOST_UBLAS_INLINE
102        ~unbounded_array () {
103            if (size_) {
104                const iterator i_end = end();
105                for (iterator i = begin (); i != i_end; ++i) {
106                    iterator_destroy (i); 
107                }
108                alloc_.deallocate (data_, size_);
109            }
110        }
111
112        // Resizing
113    private:
114        BOOST_UBLAS_INLINE
115        void resize_internal (const size_type size, const value_type init, const bool preserve) {
116            if (size != size_) {
117                pointer p_data = data_;
118                if (size) {
119                    data_ = alloc_.allocate (size);
120                    if (preserve) {
121                        pointer si = p_data;
122                        pointer di = data_;
123                        if (size < size_) {
124                            for (; di != data_ + size; ++di) {
125                                alloc_.construct (di, *si);
126                                ++si;
127                            }
128                        }
129                        else {
130                            for (pointer si = p_data; si != p_data + size_; ++si) {
131                                alloc_.construct (di, *si);
132                                ++di;
133                            }
134                            for (; di != data_ + size; ++di) {
135                                alloc_.construct (di, init);
136                            }
137                        }
138                    }
139                    else {
140                        // ISSUE some compilers may zero POD here
141#ifdef BOOST_UBLAS_USEFUL_ARRAY_PLACEMENT_NEW
142                        // array form fails on some compilers due to size cookie, is it standard conforming?
143                        new (data_) value_type[size];
144#else
145                        for (pointer di = data_; di != data_ + size; ++di)
146                            new (di) value_type;
147#endif
148                    }
149                }
150
151                if (size_) {
152                    for (pointer si = p_data; si != p_data + size_; ++si)
153                        alloc_.destroy (si);
154                    alloc_.deallocate (p_data, size_);
155                }
156
157                if (!size)
158                    data_ = 0;
159                size_ = size;
160            }
161        }
162    public:
163        BOOST_UBLAS_INLINE
164        void resize (size_type size) {
165            resize_internal (size, value_type (), false);
166        }
167        BOOST_UBLAS_INLINE
168        void resize (size_type size, value_type init) {
169            resize_internal (size, init, true);
170        }
171                   
172        // Random Access Container
173        BOOST_UBLAS_INLINE
174        size_type max_size () const {
175            return ALLOC ().max_size();
176        }
177       
178        BOOST_UBLAS_INLINE
179        bool empty () const {
180            return size_ == 0;
181        }
182           
183        BOOST_UBLAS_INLINE
184        size_type size () const {
185            return size_;
186        }
187
188        // Element access
189        BOOST_UBLAS_INLINE
190        const_reference operator [] (size_type i) const {
191            BOOST_UBLAS_CHECK (i < size_, bad_index ());
192            return data_ [i];
193        }
194        BOOST_UBLAS_INLINE
195        reference operator [] (size_type i) {
196            BOOST_UBLAS_CHECK (i < size_, bad_index ());
197            return data_ [i];
198        }
199
200        // Assignment
201        BOOST_UBLAS_INLINE
202        unbounded_array &operator = (const unbounded_array &a) {
203            if (this != &a) {
204                resize (a.size_);
205                std::copy (a.data_, a.data_ + a.size_, data_);
206            }
207            return *this;
208        }
209        BOOST_UBLAS_INLINE
210        unbounded_array &assign_temporary (unbounded_array &a) {
211            swap (a);
212            return *this;
213        }
214
215        // Swapping
216        BOOST_UBLAS_INLINE
217        void swap (unbounded_array &a) {
218            if (this != &a) {
219                std::swap (size_, a.size_);
220                std::swap (data_, a.data_);
221            }
222        }
223        BOOST_UBLAS_INLINE
224        friend void swap (unbounded_array &a1, unbounded_array &a2) {
225            a1.swap (a2);
226        }
227
228        BOOST_UBLAS_INLINE
229        const_iterator begin () const {
230            return data_;
231        }
232        BOOST_UBLAS_INLINE
233        const_iterator end () const {
234            return data_ + size_;
235        }
236
237        BOOST_UBLAS_INLINE
238        iterator begin () {
239            return data_;
240        }
241        BOOST_UBLAS_INLINE
242        iterator end () {
243            return data_ + size_;
244        }
245
246        // Reverse iterators
247        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
248        typedef std::reverse_iterator<iterator> reverse_iterator;
249
250        BOOST_UBLAS_INLINE
251        const_reverse_iterator rbegin () const {
252            return const_reverse_iterator (end ());
253        }
254        BOOST_UBLAS_INLINE
255        const_reverse_iterator rend () const {
256            return const_reverse_iterator (begin ());
257        }
258        BOOST_UBLAS_INLINE
259        reverse_iterator rbegin () {
260            return reverse_iterator (end ());
261        }
262        BOOST_UBLAS_INLINE
263        reverse_iterator rend () {
264            return reverse_iterator (begin ());
265        }
266
267        // Allocator
268        allocator_type get_allocator () {
269            return alloc_;
270        }
271
272    private:
273        // Handle explict destroy on a (possibly indexed) iterator
274        BOOST_UBLAS_INLINE
275        static void iterator_destroy (iterator &i) {
276            (&(*i)) -> ~value_type ();
277        }
278        ALLOC alloc_;
279        size_type size_;
280        pointer data_;
281    };
282
283    // Bounded array - with allocator for size_type and difference_type
284    template<class T, std::size_t N, class ALLOC>
285    class bounded_array:
286        public storage_array<bounded_array<T, N, ALLOC> > {
287
288        typedef bounded_array<T, N, ALLOC> self_type;
289    public:
290        // No allocator_type as ALLOC is not used for allocation
291        typedef typename ALLOC::size_type size_type;
292        typedef typename ALLOC::difference_type difference_type;
293        typedef T value_type;
294        typedef const T &const_reference;
295        typedef T &reference;
296        typedef const T *const_pointer;
297        typedef T *pointer;
298        typedef const_pointer const_iterator;
299        typedef pointer iterator;
300
301        // Construction and destruction
302        BOOST_UBLAS_INLINE
303        bounded_array ():
304            size_ (0) /*, data_ ()*/ {   // size 0 - use bounded_vector to default construct with size N
305        }
306        explicit BOOST_UBLAS_INLINE
307        bounded_array (size_type size):
308            size_ (size) /*, data_ ()*/ {
309            BOOST_UBLAS_CHECK (size_ <= N, bad_size ());
310            // data_ (an array) elements are already default constructed
311        }
312        BOOST_UBLAS_INLINE
313        bounded_array (size_type size, const value_type &init):
314            size_ (size) /*, data_ ()*/ {
315            BOOST_UBLAS_CHECK (size_ <= N, bad_size ());
316            // ISSUE elements should be value constructed here, but we must fill instead as already default constructed
317            std::fill (begin(), end(), init) ;
318        }
319        BOOST_UBLAS_INLINE
320        bounded_array (const bounded_array &c):
321            size_ (c.size_)  {
322            // ISSUE elements should be copy constructed here, but we must copy instead as already default constructed
323            std::copy (c.data_, c.data_ + c.size_, data_);
324        }
325       
326        // Resizing
327        BOOST_UBLAS_INLINE
328        void resize (size_type size) {
329            BOOST_UBLAS_CHECK (size_ <= N, bad_size ());
330            size_ = size;
331        }
332        BOOST_UBLAS_INLINE
333        void resize (size_type size, value_type init) {
334            BOOST_UBLAS_CHECK (size_ <= N, bad_size ());
335            if (size > size_)
336                std::fill (data_ + size_, data_ + size, init);
337            size_ = size;
338        }
339
340        // Random Access Container
341        BOOST_UBLAS_INLINE
342        size_type max_size () const {
343            return ALLOC ().max_size();
344        }
345       
346        BOOST_UBLAS_INLINE
347        bool empty () const {
348            return size_ == 0;
349        }
350           
351        BOOST_UBLAS_INLINE
352        size_type size () const {
353            return size_;
354        }
355
356        // Element access
357        BOOST_UBLAS_INLINE
358        const_reference operator [] (size_type i) const {
359            BOOST_UBLAS_CHECK (i < size_, bad_index ());
360            return data_ [i];
361        }
362        BOOST_UBLAS_INLINE
363        reference operator [] (size_type i) {
364            BOOST_UBLAS_CHECK (i < size_, bad_index ());
365            return data_ [i];
366        }
367
368        // Assignment
369        BOOST_UBLAS_INLINE
370        bounded_array &operator = (const bounded_array &a) {
371            if (this != &a) {
372                resize (a.size_);
373                std::copy (a.data_, a.data_ + a.size_, data_);
374            }
375            return *this;
376        }
377        BOOST_UBLAS_INLINE
378        bounded_array &assign_temporary (bounded_array &a) { 
379            *this = a;
380            return *this;
381        }
382
383        // Swapping
384        BOOST_UBLAS_INLINE
385        void swap (bounded_array &a) {
386            if (this != &a) {
387                std::swap (size_, a.size_);
388                std::swap_ranges (data_, data_ + (std::max) (size_, a.size_), a.data_);
389            }
390        }
391        BOOST_UBLAS_INLINE
392        friend void swap (bounded_array &a1, bounded_array &a2) {
393            a1.swap (a2);
394        }
395
396        BOOST_UBLAS_INLINE
397        const_iterator begin () const {
398            return data_;
399        }
400        BOOST_UBLAS_INLINE
401        const_iterator end () const {
402            return data_ + size_;
403        }
404
405        BOOST_UBLAS_INLINE
406        iterator begin () {
407            return data_;
408        }
409        BOOST_UBLAS_INLINE
410        iterator end () {
411            return data_ + size_;
412        }
413
414        // Reverse iterators
415        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
416        typedef std::reverse_iterator<iterator> reverse_iterator;
417
418        BOOST_UBLAS_INLINE
419        const_reverse_iterator rbegin () const {
420            return const_reverse_iterator (end ());
421        }
422        BOOST_UBLAS_INLINE
423        const_reverse_iterator rend () const {
424            return const_reverse_iterator (begin ());
425        }
426        BOOST_UBLAS_INLINE
427        reverse_iterator rbegin () {
428            return reverse_iterator (end ());
429        }
430        BOOST_UBLAS_INLINE
431        reverse_iterator rend () {
432            return reverse_iterator (begin ());
433        }
434
435    private:
436        size_type size_;
437        BOOST_UBLAS_BOUNDED_ARRAY_ALIGN value_type data_ [N];
438    };
439
440
441    // Array adaptor with normal deep copy semantics of elements
442    template<class T>
443    class array_adaptor:
444        public storage_array<array_adaptor<T> > {
445
446        typedef array_adaptor<T> self_type;
447    public:
448        typedef std::size_t size_type;
449        typedef std::ptrdiff_t difference_type;
450        typedef T value_type;
451        typedef const T &const_reference;
452        typedef T &reference;
453        typedef const T *const_pointer;
454        typedef T *pointer;
455
456        // Construction and destruction
457        BOOST_UBLAS_INLINE
458        array_adaptor ():
459            size_ (0), own_ (true), data_ (new value_type [0]) {
460        }
461        explicit BOOST_UBLAS_INLINE
462        array_adaptor (size_type size):
463            size_ (size), own_ (true), data_ (new value_type [size]) {
464        }
465        BOOST_UBLAS_INLINE
466        array_adaptor (size_type size, const value_type &init):
467            size_ (size), own_ (true), data_ (new value_type [size]) {
468            std::fill (data_, data_ + size_, init);
469        }
470        BOOST_UBLAS_INLINE
471        array_adaptor (size_type size, pointer data):
472            size_ (size), own_ (false), data_ (data) {}
473        BOOST_UBLAS_INLINE
474        array_adaptor (const array_adaptor &a):
475            storage_array<self_type> (),
476            size_ (a.size_), own_ (true), data_ (new value_type [a.size_]) {
477            *this = a;
478        }
479        BOOST_UBLAS_INLINE
480        ~array_adaptor () {
481            if (own_) {
482                delete [] data_;
483            }
484        }
485
486        // Resizing
487    private:
488        BOOST_UBLAS_INLINE
489        void resize_internal (size_type size, value_type init, bool preserve = true) {
490           if (size != size_) {
491                pointer data = new value_type [size];
492                if (preserve) {
493                    std::copy (data_, data_ + (std::min) (size, size_), data);
494                    std::fill (data + (std::min) (size, size_), data + size, init);
495                }
496                if (own_)
497                    delete [] data_;
498                size_ = size;
499                own_ = true;
500                data_ = data;
501            }
502        }
503        BOOST_UBLAS_INLINE
504        void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) {
505            if (data != data_) {
506                if (preserve) {
507                    std::copy (data_, data_ + (std::min) (size, size_), data);
508                    std::fill (data + (std::min) (size, size_), data + size, init);
509                }
510                if (own_)
511                    delete [] data_;
512                own_ = false;
513                data_ = data;
514            }
515            else {
516                std::fill (data + (std::min) (size, size_), data + size, init);
517            }
518            size_ = size;
519        }
520    public:
521        BOOST_UBLAS_INLINE
522        void resize (size_type size) {
523            resize_internal (size, value_type (), false);
524        }
525        BOOST_UBLAS_INLINE
526        void resize (size_type size, value_type init) {
527            resize_internal (size, init, true);
528        }
529        BOOST_UBLAS_INLINE
530        void resize (size_type size, pointer data) {
531            resize_internal (size, data, value_type (), false);
532        }
533        BOOST_UBLAS_INLINE
534        void resize (size_type size, pointer data, value_type init) {
535            resize_internal (size, data, init, true);
536        }
537
538        BOOST_UBLAS_INLINE
539        size_type size () const {
540            return size_;
541        }
542
543        // Element access
544        BOOST_UBLAS_INLINE
545        const_reference operator [] (size_type i) const {
546            BOOST_UBLAS_CHECK (i < size_, bad_index ());
547            return data_ [i];
548        }
549        BOOST_UBLAS_INLINE
550        reference operator [] (size_type i) {
551            BOOST_UBLAS_CHECK (i < size_, bad_index ());
552            return data_ [i];
553        }
554
555        // Assignment
556        BOOST_UBLAS_INLINE
557        array_adaptor &operator = (const array_adaptor &a) {
558            if (this != &a) {
559                resize (a.size_);
560                std::copy (a.data_, a.data_ + a.size_, data_);
561            }
562            return *this;
563        }
564        BOOST_UBLAS_INLINE
565        array_adaptor &assign_temporary (array_adaptor &a) {
566            if (own_ && a.own_)
567                swap (a);
568            else
569                *this = a;
570            return *this;
571        }
572
573        // Swapping
574        BOOST_UBLAS_INLINE
575        void swap (array_adaptor &a) {
576            if (this != &a) {
577                std::swap (size_, a.size_);
578                std::swap (own_, a.own_);
579                std::swap (data_, a.data_);
580            }
581        }
582        BOOST_UBLAS_INLINE
583        friend void swap (array_adaptor &a1, array_adaptor &a2) {
584            a1.swap (a2);
585        }
586
587        // Iterators simply are pointers.
588
589        typedef const_pointer const_iterator;
590
591        BOOST_UBLAS_INLINE
592        const_iterator begin () const {
593            return data_;
594        }
595        BOOST_UBLAS_INLINE
596        const_iterator end () const {
597            return data_ + size_;
598        }
599
600        typedef pointer iterator;
601
602        BOOST_UBLAS_INLINE
603        iterator begin () {
604            return data_;
605        }
606        BOOST_UBLAS_INLINE
607        iterator end () {
608            return data_ + size_;
609        }
610
611        // Reverse iterators
612        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
613        typedef std::reverse_iterator<iterator> reverse_iterator;
614
615        BOOST_UBLAS_INLINE
616        const_reverse_iterator rbegin () const {
617            return const_reverse_iterator (end ());
618        }
619        BOOST_UBLAS_INLINE
620        const_reverse_iterator rend () const {
621            return const_reverse_iterator (begin ());
622        }
623        BOOST_UBLAS_INLINE
624        reverse_iterator rbegin () {
625            return reverse_iterator (end ());
626        }
627        BOOST_UBLAS_INLINE
628        reverse_iterator rend () {
629            return reverse_iterator (begin ());
630        }
631
632    private:
633        size_type size_;
634        bool own_;
635        pointer data_;
636    };
637
638#ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR
639    // Array adaptor with shallow (reference) copy semantics of elements.
640    // shared_array is used to maintain reference counts.
641    // This class breaks the normal copy semantics for a storage container and is very dangerous!
642    template<class T>
643    class shallow_array_adaptor:
644        public storage_array<shallow_array_adaptor<T> > {
645
646        typedef shallow_array_adaptor<T> self_type;
647
648        template<class TT>
649        struct leaker {
650            typedef void result_type;
651            typedef TT *argument_type;
652
653            BOOST_UBLAS_INLINE
654            result_type operator () (argument_type x) {}
655        };
656
657    public:
658        typedef std::size_t size_type;
659        typedef std::ptrdiff_t difference_type;
660        typedef T value_type;
661        typedef const T &const_reference;
662        typedef T &reference;
663        typedef const T *const_pointer;
664        typedef T *pointer;
665
666        // Construction and destruction
667        BOOST_UBLAS_INLINE
668        shallow_array_adaptor ():
669            size_ (0), own_ (true), data_ (new value_type [0]) {
670        }
671        explicit BOOST_UBLAS_INLINE
672        shallow_array_adaptor (size_type size):
673            size_ (size), own_ (true), data_ (new value_type [size]) {
674        }
675        BOOST_UBLAS_INLINE
676        shallow_array_adaptor (size_type size, const value_type &init):
677            size_ (size), own_ (true), data_ (new value_type [size]) {
678            std::fill (data_.get (), data_.get () + size_, init);
679        }
680        BOOST_UBLAS_INLINE
681        shallow_array_adaptor (size_type size, pointer data):
682            size_ (size), own_ (false), data_ (data, leaker<value_type> ()) {}
683
684        BOOST_UBLAS_INLINE
685        shallow_array_adaptor (const shallow_array_adaptor &a):
686            storage_array<self_type> (),
687            size_ (a.size_), own_ (a.own_), data_ (a.data_) {}
688
689        BOOST_UBLAS_INLINE
690        ~shallow_array_adaptor () {
691        }
692
693        // Resizing
694    private:
695        BOOST_UBLAS_INLINE
696        void resize_internal (size_type size, value_type init, bool preserve = true) {
697            if (size != size_) {
698                shared_array<value_type> data (new value_type [size]);
699                if (preserve) {
700                    std::copy (data_.get (), data_.get () + (std::min) (size, size_), data.get ());
701                    std::fill (data.get () + (std::min) (size, size_), data.get () + size, init);
702                }
703                size_ = size;
704                data_ = data;
705            }
706        }
707        BOOST_UBLAS_INLINE
708        void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) {
709            if (preserve) {
710                std::copy (data_.get (), data_.get () + (std::min) (size, size_), data);
711                std::fill (data + (std::min) (size, size_), data + size, init);
712            }
713            size_ = size;
714            data_ = data;
715        }
716    public:
717        BOOST_UBLAS_INLINE
718        void resize (size_type size) {
719            resize_internal (size, value_type (), false);
720        }
721        BOOST_UBLAS_INLINE
722        void resize (size_type size, value_type init) {
723            resize_internal (size, init, true);
724        }
725        BOOST_UBLAS_INLINE
726        void resize (size_type size, pointer data) {
727            resize_internal (size, data, value_type (), false);
728        }
729        BOOST_UBLAS_INLINE
730        void resize (size_type size, pointer data, value_type init) {
731            resize_internal (size, data, init, true);
732        }
733
734        BOOST_UBLAS_INLINE
735        size_type size () const {
736            return size_;
737        }
738
739        // Element access
740        BOOST_UBLAS_INLINE
741        const_reference operator [] (size_type i) const {
742            BOOST_UBLAS_CHECK (i < size_, bad_index ());
743            return data_ [i];
744        }
745        BOOST_UBLAS_INLINE
746        reference operator [] (size_type i) {
747            BOOST_UBLAS_CHECK (i < size_, bad_index ());
748            return data_ [i];
749        }
750
751        // Assignment
752        BOOST_UBLAS_INLINE
753        shallow_array_adaptor &operator = (const shallow_array_adaptor &a) {
754            if (this != &a) {
755                resize (a.size_);
756                std::copy (a.data_.get (), a.data_.get () + a.size_, data_.get ());
757            }
758            return *this;
759        }
760        BOOST_UBLAS_INLINE
761        shallow_array_adaptor &assign_temporary (shallow_array_adaptor &a) {
762            if (own_ && a.own_)
763                swap (a);
764            else
765                *this = a;
766            return *this;
767        }
768
769        // Swapping
770        BOOST_UBLAS_INLINE
771        void swap (shallow_array_adaptor &a) {
772            if (this != &a) {
773                std::swap (size_, a.size_);
774                std::swap (own_, a.own_);
775                std::swap (data_, a.data_);
776            }
777        }
778        BOOST_UBLAS_INLINE
779        friend void swap (shallow_array_adaptor &a1, shallow_array_adaptor &a2) {
780            a1.swap (a2);
781        }
782
783        // Iterators simply are pointers.
784
785        typedef const_pointer const_iterator;
786
787        BOOST_UBLAS_INLINE
788        const_iterator begin () const {
789            return data_.get ();
790        }
791        BOOST_UBLAS_INLINE
792        const_iterator end () const {
793            return data_.get () + size_;
794        }
795
796        typedef pointer iterator;
797
798        BOOST_UBLAS_INLINE
799        iterator begin () {
800            return data_.get ();
801        }
802        BOOST_UBLAS_INLINE
803        iterator end () {
804            return data_.get () + size_;
805        }
806
807        // Reverse iterators
808        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
809        typedef std::reverse_iterator<iterator> reverse_iterator;
810
811        BOOST_UBLAS_INLINE
812        const_reverse_iterator rbegin () const {
813            return const_reverse_iterator (end ());
814        }
815        BOOST_UBLAS_INLINE
816        const_reverse_iterator rend () const {
817            return const_reverse_iterator (begin ());
818        }
819        BOOST_UBLAS_INLINE
820        reverse_iterator rbegin () {
821            return reverse_iterator (end ());
822        }
823        BOOST_UBLAS_INLINE
824        reverse_iterator rend () {
825            return reverse_iterator (begin ());
826        }
827
828    private:
829        size_type size_;
830        bool own_;
831        shared_array<value_type> data_;
832    };
833
834#endif
835
836
837    // Range class
838    template <class Z, class D>
839    class basic_range {
840        typedef basic_range<Z, D> self_type;
841    public:
842        typedef Z size_type;
843        typedef D difference_type;
844        typedef size_type value_type;
845        typedef value_type const_reference;
846        typedef const_reference reference;
847        typedef const value_type *const_pointer;
848        typedef value_type *pointer;
849
850        // Construction and destruction
851        BOOST_UBLAS_INLINE
852        basic_range ():
853            start_ (0), size_ (0) {}
854        BOOST_UBLAS_INLINE
855        basic_range (size_type start, size_type stop):
856            start_ (start), size_ (stop - start) {
857            BOOST_UBLAS_CHECK (start_ <= stop, bad_index ());
858        }
859
860        BOOST_UBLAS_INLINE
861        size_type start () const {
862            return start_;
863        }
864        BOOST_UBLAS_INLINE
865        size_type size () const {
866            return size_;
867        }
868
869        // Random Access Container
870        BOOST_UBLAS_INLINE
871        size_type max_size () const {
872            return size_;
873        }
874       
875        BOOST_UBLAS_INLINE
876        bool empty () const {
877            return size_ == 0;
878        }
879           
880        // Element access
881        BOOST_UBLAS_INLINE
882        const_reference operator () (size_type i) const {
883            BOOST_UBLAS_CHECK (i < size_, bad_index ());
884            return start_ + i;
885        }
886
887        // Composition
888        BOOST_UBLAS_INLINE
889        basic_range compose (const basic_range &r) const {
890            return basic_range (start_ + r.start_, start_ + r.start_ + r.size_);
891        }
892
893        // Comparison
894        BOOST_UBLAS_INLINE
895        bool operator == (const basic_range &r) const {
896            return start_ == r.start_ && size_ == r.size_;
897        }
898        BOOST_UBLAS_INLINE
899        bool operator != (const basic_range &r) const {
900            return ! (*this == r);
901        }
902
903        // Iterator types
904    private:
905        // Use and index
906        typedef size_type const_subiterator_type;
907
908    public:
909#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
910        typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator;
911#else
912        class const_iterator:
913            public container_const_reference<basic_range>,
914            public random_access_iterator_base<std::random_access_iterator_tag,
915                                               const_iterator, value_type> {
916        public:
917            typedef typename basic_range::value_type value_type;
918            typedef typename basic_range::difference_type difference_type;
919            typedef typename basic_range::const_reference reference;
920            typedef typename basic_range::const_pointer pointer;
921
922            // Construction and destruction
923            BOOST_UBLAS_INLINE
924            const_iterator ():
925                container_const_reference<basic_range> (), it_ () {}
926            BOOST_UBLAS_INLINE
927            const_iterator (const basic_range &r, const const_subiterator_type &it):
928                container_const_reference<basic_range> (r), it_ (it) {}
929
930            // Arithmetic
931            BOOST_UBLAS_INLINE
932            const_iterator &operator ++ () {
933                ++ it_;
934                return *this;
935            }
936            BOOST_UBLAS_INLINE
937            const_iterator &operator -- () {
938                BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
939                -- it_;
940                return *this;
941            }
942            BOOST_UBLAS_INLINE
943            const_iterator &operator += (difference_type n) {
944                BOOST_UBLAS_CHECK (n >= 0 || it_ >= size_type(-n), bad_index ());
945                it_ += n;
946                return *this;
947            }
948            BOOST_UBLAS_INLINE
949            const_iterator &operator -= (difference_type n) {
950                BOOST_UBLAS_CHECK (n <= 0 || it_ >= size_type(n), bad_index ());
951                it_ -= n;
952                return *this;
953            }
954            BOOST_UBLAS_INLINE
955            difference_type operator - (const const_iterator &it) const {
956                return it_ - it.it_;
957            }
958
959            // Dereference
960            BOOST_UBLAS_INLINE
961            const_reference operator * () const {
962                BOOST_UBLAS_CHECK ((*this) ().start () <= it_, bad_index ());
963                BOOST_UBLAS_CHECK (it_ < (*this) ().start () + (*this) ().size (), bad_index ());
964                return it_;
965            }
966
967            BOOST_UBLAS_INLINE
968            const_reference operator [] (difference_type n) const {
969                return *(*this + n);
970            }
971
972            // Index
973            BOOST_UBLAS_INLINE
974            size_type index () const {
975                BOOST_UBLAS_CHECK ((*this) ().start () <= it_, bad_index ());
976                BOOST_UBLAS_CHECK (it_ < (*this) ().start () + (*this) ().size (), bad_index ());
977                return it_ - (*this) ().start ();
978            }
979
980            // Assignment
981            BOOST_UBLAS_INLINE
982            const_iterator &operator = (const const_iterator &it) {
983                // Comeau recommends...
984                this->assign (&it ());
985                it_ = it.it_;
986                return *this;
987            }
988
989            // Comparison
990            BOOST_UBLAS_INLINE
991            bool operator == (const const_iterator &it) const {
992                BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
993                return it_ == it.it_;
994            }
995            BOOST_UBLAS_INLINE
996            bool operator < (const const_iterator &it) const {
997                BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
998                return it_ < it.it_;
999            }
1000
1001        private:
1002            const_subiterator_type it_;
1003        };
1004#endif
1005
1006        BOOST_UBLAS_INLINE
1007        const_iterator begin () const {
1008            return const_iterator (*this, start_);
1009        }
1010        BOOST_UBLAS_INLINE
1011        const_iterator end () const {
1012            return const_iterator (*this, start_ + size_);
1013        }
1014
1015        // Reverse iterator
1016        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1017
1018        BOOST_UBLAS_INLINE
1019        const_reverse_iterator rbegin () const {
1020            return const_reverse_iterator (end ());
1021        }
1022        BOOST_UBLAS_INLINE
1023        const_reverse_iterator rend () const {
1024            return const_reverse_iterator (begin ());
1025        }
1026
1027        BOOST_UBLAS_INLINE
1028        basic_range preprocess (size_type size) const {
1029            if (this != &all_)
1030                return *this;
1031            return basic_range (0, size);
1032        }
1033        static
1034        BOOST_UBLAS_INLINE
1035        const basic_range &all () {
1036            return all_;
1037        }
1038
1039    private:
1040        size_type start_;
1041        size_type size_;
1042        static const basic_range all_;
1043    };
1044
1045    template <class Z, class D>
1046    const basic_range<Z,D> basic_range<Z,D>::all_  (0, size_type (-1));
1047
1048
1049    // Slice class
1050    template <class Z, class D>
1051    class basic_slice {
1052        typedef basic_slice<Z, D> self_type;
1053    public:
1054        typedef Z size_type;
1055        typedef D difference_type;
1056        typedef size_type value_type;
1057        typedef value_type const_reference;
1058        typedef const_reference reference;
1059        typedef const value_type *const_pointer;
1060        typedef value_type *pointer;
1061
1062        // Construction and destruction
1063        BOOST_UBLAS_INLINE
1064        basic_slice ():
1065            start_ (0), stride_ (0), size_ (0) {}
1066        BOOST_UBLAS_INLINE
1067        basic_slice (size_type start, difference_type stride, size_type size):
1068            start_ (start), stride_ (stride), size_ (size) {}
1069
1070        BOOST_UBLAS_INLINE
1071        size_type start () const {
1072            return start_;
1073        }
1074        BOOST_UBLAS_INLINE
1075        difference_type stride () const {
1076            return stride_;
1077        }
1078        BOOST_UBLAS_INLINE
1079        size_type size () const {
1080            return size_;
1081        }
1082
1083        // Random Access Container
1084        BOOST_UBLAS_INLINE
1085        size_type max_size () const {
1086            return size_;
1087        }
1088       
1089        BOOST_UBLAS_INLINE
1090        bool empty () const {
1091            return size_ == 0;
1092        }
1093           
1094        // Element access
1095        BOOST_UBLAS_INLINE
1096        const_reference operator () (size_type i) const {
1097            BOOST_UBLAS_CHECK (i < size_, bad_index ());
1098            BOOST_UBLAS_CHECK (stride_ >= 0 || start_ >= i * -stride_, bad_index ());
1099            return start_ + i * stride_;
1100        }
1101
1102        // Composition
1103        BOOST_UBLAS_INLINE
1104        basic_slice compose (const basic_range<size_type, difference_type> &r) const {
1105            BOOST_UBLAS_CHECK (stride_ >=0 || start_ >= -stride_ * r.start(), bad_index ());
1106            return basic_slice (start_ + stride_ * r.start (), stride_, r.size ());
1107        }
1108        BOOST_UBLAS_INLINE
1109        basic_slice compose (const basic_slice &s) const {
1110            BOOST_UBLAS_CHECK (stride_ >=0 || start_ >= -stride_ * s.start_, bad_index ());
1111            return basic_slice (start_ + stride_ * s.start_, stride_ * s.stride_, s.size_);
1112        }
1113
1114        // Comparison
1115        BOOST_UBLAS_INLINE
1116        bool operator == (const basic_slice &s) const {
1117            return start_ == s.start_ && stride_ == s.stride_ && size_ == s.size_; 
1118        }
1119        BOOST_UBLAS_INLINE
1120        bool operator != (const basic_slice &s) const {
1121            return ! (*this == s);
1122        }
1123
1124        // Iterator types
1125    private:
1126        // Use and index
1127        typedef size_type const_subiterator_type;
1128
1129    public:
1130#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1131        typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator;
1132#else
1133        class const_iterator:
1134            public container_const_reference<basic_slice>,
1135            public random_access_iterator_base<std::random_access_iterator_tag,
1136                                               const_iterator, value_type> {
1137        public:
1138            typedef typename basic_slice::value_type value_type;
1139            typedef typename basic_slice::difference_type difference_type;
1140            typedef typename basic_slice::const_reference reference;
1141            typedef typename basic_slice::const_pointer pointer;
1142
1143            // Construction and destruction
1144            BOOST_UBLAS_INLINE
1145            const_iterator ():
1146                container_const_reference<basic_slice> (), it_ () {}
1147            BOOST_UBLAS_INLINE
1148            const_iterator (const basic_slice &s, const const_subiterator_type &it):
1149                container_const_reference<basic_slice> (s), it_ (it) {}
1150
1151            // Arithmetic
1152            BOOST_UBLAS_INLINE
1153            const_iterator &operator ++ () {
1154                ++it_;
1155                return *this;
1156            }
1157            BOOST_UBLAS_INLINE
1158            const_iterator &operator -- () {
1159                BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
1160                --it_;
1161                return *this;
1162            }
1163            BOOST_UBLAS_INLINE
1164            const_iterator &operator += (difference_type n) {
1165                BOOST_UBLAS_CHECK (n >= 0 || it_ >= size_type(-n), bad_index ());
1166                it_ += n;
1167                return *this;
1168            }
1169            BOOST_UBLAS_INLINE
1170            const_iterator &operator -= (difference_type n) {
1171                BOOST_UBLAS_CHECK (n <= 0 || it_ >= size_type(n), bad_index ());
1172                it_ -= n;
1173                return *this;
1174            }
1175            BOOST_UBLAS_INLINE
1176            difference_type operator - (const const_iterator &it) const {
1177                return it_ - it.it_;
1178            }
1179
1180            // Dereference
1181            BOOST_UBLAS_INLINE
1182            const_reference operator * () const {
1183                BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ());
1184                return (*this) ().start () + it_* (*this) ().stride ();
1185            }
1186
1187            BOOST_UBLAS_INLINE
1188            const_reference operator [] (difference_type n) const {
1189                return *(*this + n);
1190            }
1191
1192            // Index
1193            BOOST_UBLAS_INLINE
1194            size_type index () const {
1195                BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ());
1196                return it_;
1197            }
1198
1199            // Assignment
1200            BOOST_UBLAS_INLINE
1201            const_iterator &operator = (const const_iterator &it) {
1202                // Comeau recommends...
1203                this->assign (&it ());
1204                it_ = it.it_;
1205                return *this;
1206            }
1207
1208            // Comparison
1209            BOOST_UBLAS_INLINE
1210            bool operator == (const const_iterator &it) const {
1211                BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
1212                return it_ == it.it_;
1213            }
1214            BOOST_UBLAS_INLINE
1215            bool operator < (const const_iterator &it) const {
1216                BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
1217                return it_ < it.it_;
1218            }
1219
1220        private:
1221            const_subiterator_type it_;
1222        };
1223#endif
1224
1225        BOOST_UBLAS_INLINE
1226        const_iterator begin () const {
1227            return const_iterator (*this, 0);
1228        }
1229        BOOST_UBLAS_INLINE
1230        const_iterator end () const {
1231            return const_iterator (*this, size_);
1232        }
1233
1234        // Reverse iterator
1235        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1236
1237        BOOST_UBLAS_INLINE
1238        const_reverse_iterator rbegin () const {
1239            return const_reverse_iterator (end ());
1240        }
1241        BOOST_UBLAS_INLINE
1242        const_reverse_iterator rend () const {
1243            return const_reverse_iterator (begin ());
1244        }
1245
1246        BOOST_UBLAS_INLINE
1247        basic_slice preprocess (size_type size) const {
1248            if (this != &all_)
1249                return *this;
1250            return basic_slice (0, 1, size);
1251        }
1252        static
1253        BOOST_UBLAS_INLINE
1254        const basic_slice &all () {
1255            return all_;
1256        }
1257
1258    private:
1259        size_type start_;
1260        difference_type stride_;
1261        size_type size_;
1262        static const basic_slice all_;
1263    };
1264
1265    template <class Z, class D>
1266    const basic_slice<Z,D> basic_slice<Z,D>::all_  (0, 1, size_type (-1));
1267
1268
1269    // Indirect array class
1270    template<class A>
1271    class indirect_array {
1272        typedef indirect_array<A> self_type;
1273    public:
1274        typedef A array_type;
1275        typedef const A const_array_type;
1276        typedef typename A::size_type size_type;
1277        typedef typename A::difference_type difference_type;
1278        typedef typename A::value_type value_type;
1279        typedef typename A::const_reference const_reference;
1280        typedef typename A::reference reference;
1281        typedef typename A::const_pointer const_pointer;
1282        typedef typename A::pointer pointer;
1283
1284        // Construction and destruction
1285        BOOST_UBLAS_INLINE
1286        indirect_array ():
1287            size_ (), data_ () {}
1288        explicit BOOST_UBLAS_INLINE
1289        indirect_array (size_type size):
1290            size_ (size), data_ (size) {}
1291        BOOST_UBLAS_INLINE
1292        indirect_array (size_type size, const array_type &data):
1293            size_ (size), data_ (data) {}
1294        BOOST_UBLAS_INLINE
1295        indirect_array (pointer start, pointer stop):
1296            size_ (stop - start), data_ (stop - start) {
1297            std::copy (start, stop, data_.begin ());
1298        }
1299
1300        BOOST_UBLAS_INLINE
1301        size_type size () const {
1302            return size_;
1303        }
1304        BOOST_UBLAS_INLINE
1305        const_array_type data () const {
1306            return data_;
1307        }
1308        BOOST_UBLAS_INLINE
1309        array_type data () {
1310            return data_;
1311        }
1312
1313        // Random Access Container
1314        BOOST_UBLAS_INLINE
1315        size_type max_size () const {
1316            return size_;
1317        }
1318       
1319        BOOST_UBLAS_INLINE
1320        bool empty () const {
1321            return data_.size () == 0;
1322        }
1323           
1324        // Element access
1325        BOOST_UBLAS_INLINE
1326        const_reference operator () (size_type i) const {
1327            BOOST_UBLAS_CHECK (i < size_, bad_index ());
1328            return data_ [i];
1329        }
1330        BOOST_UBLAS_INLINE
1331        reference operator () (size_type i) {
1332            BOOST_UBLAS_CHECK (i < size_, bad_index ());
1333            return data_ [i];
1334        }
1335
1336        BOOST_UBLAS_INLINE
1337        const_reference operator [] (size_type i) const {
1338            return (*this) (i);
1339        }
1340        BOOST_UBLAS_INLINE
1341        reference operator [] (size_type i) {
1342            return (*this) (i);
1343        }
1344
1345        // Composition
1346        BOOST_UBLAS_INLINE
1347        indirect_array compose (const basic_range<size_type, difference_type> &r) const {
1348            BOOST_UBLAS_CHECK (r.start () + r.size () <= size_, bad_size ());
1349            array_type data (r.size ());
1350            for (size_type i = 0; i < r.size (); ++ i)
1351                data [i] = data_ [r.start () + i];
1352            return indirect_array (r.size (), data);
1353        }
1354        BOOST_UBLAS_INLINE
1355        indirect_array compose (const basic_slice<size_type, difference_type> &s) const {
1356            BOOST_UBLAS_CHECK (s.start () + s.stride () * (s.size () - (s.size () > 0)) <= size (), bad_size ());
1357            array_type data (s.size ());
1358            for (size_type i = 0; i < s.size (); ++ i)
1359                data [i] = data_ [s.start () + s.stride () * i];
1360            return indirect_array (s.size (), data);
1361        }
1362        BOOST_UBLAS_INLINE
1363        indirect_array compose (const indirect_array &ia) const {
1364            array_type data (ia.size_);
1365            for (size_type i = 0; i < ia.size_; ++ i) {
1366                BOOST_UBLAS_CHECK (ia.data_ [i] <= size_, bad_size ());
1367                data [i] = data_ [ia.data_ [i]];
1368            }
1369            return indirect_array (ia.size_, data);
1370        }
1371
1372        // Comparison
1373        template<class OA>
1374        BOOST_UBLAS_INLINE
1375        bool operator == (const indirect_array<OA> &ia) const {
1376            if (size_ != ia.size_)
1377                return false;
1378            for (size_type i = 0; i < BOOST_UBLAS_SAME (size_, ia.size_); ++ i)
1379                if (data_ [i] != ia.data_ [i])
1380                    return false;
1381            return true;
1382        }
1383        template<class OA>
1384        BOOST_UBLAS_INLINE
1385        bool operator != (const indirect_array<OA> &ia) const {
1386            return ! (*this == ia);
1387        }
1388
1389        // Iterator types
1390    private:
1391        // Use a index difference
1392        typedef difference_type const_subiterator_type;
1393
1394    public:
1395#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1396        typedef indexed_const_iterator<indirect_array, std::random_access_iterator_tag> const_iterator;
1397#else
1398        class const_iterator:
1399            public container_const_reference<indirect_array>,
1400            public random_access_iterator_base<std::random_access_iterator_tag,
1401                                               const_iterator, value_type> {
1402        public:
1403            typedef typename indirect_array::value_type value_type;
1404            typedef typename indirect_array::difference_type difference_type;
1405            typedef typename indirect_array::const_reference reference;
1406            typedef typename indirect_array::const_pointer pointer;
1407
1408            // Construction and destruction
1409            BOOST_UBLAS_INLINE
1410            const_iterator ():
1411                container_const_reference<indirect_array> (), it_ () {}
1412            BOOST_UBLAS_INLINE
1413            const_iterator (const indirect_array &ia, const const_subiterator_type &it):
1414                container_const_reference<indirect_array> (ia), it_ (it) {}
1415
1416            // Arithmetic
1417            BOOST_UBLAS_INLINE
1418            const_iterator &operator ++ () {
1419                ++ it_;
1420                return *this;
1421            }
1422            BOOST_UBLAS_INLINE
1423            const_iterator &operator -- () {
1424                -- it_;
1425                return *this;
1426            }
1427            BOOST_UBLAS_INLINE
1428            const_iterator &operator += (difference_type n) {
1429                it_ += n;
1430                return *this;
1431            }
1432            BOOST_UBLAS_INLINE
1433            const_iterator &operator -= (difference_type n) {
1434                it_ -= n;
1435                return *this;
1436            }
1437            BOOST_UBLAS_INLINE
1438            difference_type operator - (const const_iterator &it) const {
1439                return it_ - it.it_;
1440            }
1441
1442            // Dereference
1443            BOOST_UBLAS_INLINE
1444            const_reference operator * () const {
1445                return (*this) () (it_);
1446            }
1447
1448            BOOST_UBLAS_INLINE
1449            const_reference operator [] (difference_type n) const {
1450                return *(*this + n);
1451            }
1452
1453            // Index
1454            BOOST_UBLAS_INLINE
1455            size_type index () const {
1456                return it_;
1457            }
1458
1459            // Assignment
1460            BOOST_UBLAS_INLINE
1461            const_iterator &operator = (const const_iterator &it) {
1462                // Comeau recommends...
1463                this->assign (&it ());
1464                it_ = it.it_;
1465                return *this;
1466            }
1467
1468            // Comparison
1469            BOOST_UBLAS_INLINE
1470            bool operator == (const const_iterator &it) const {
1471                BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
1472                return it_ == it.it_;
1473            }
1474            BOOST_UBLAS_INLINE
1475            bool operator < (const const_iterator &it) const {
1476                BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
1477                return it_ < it.it_;
1478            }
1479
1480        private:
1481            const_subiterator_type it_;
1482        };
1483#endif
1484
1485        BOOST_UBLAS_INLINE
1486        const_iterator begin () const {
1487            return const_iterator (*this, 0);
1488        }
1489        BOOST_UBLAS_INLINE
1490        const_iterator end () const {
1491            return const_iterator (*this, size_);
1492        }
1493
1494        // Reverse iterator
1495        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1496
1497        BOOST_UBLAS_INLINE
1498        const_reverse_iterator rbegin () const {
1499            return const_reverse_iterator (end ());
1500        }
1501        BOOST_UBLAS_INLINE
1502        const_reverse_iterator rend () const {
1503            return const_reverse_iterator (begin ());
1504        }
1505
1506        BOOST_UBLAS_INLINE
1507        indirect_array preprocess (size_type size) const {
1508            if (this != &all_)
1509                return *this;
1510            indirect_array ia (size);
1511            for (size_type i = 0; i < size; ++ i)
1512               ia (i) = i;
1513            return ia;
1514        }
1515        static
1516        BOOST_UBLAS_INLINE
1517        const indirect_array &all () {
1518            return all_;
1519        }
1520
1521    private:
1522        size_type size_;
1523        array_type data_;
1524        static const indirect_array all_;
1525    };
1526
1527    template<class A>
1528    const indirect_array<A> indirect_array<A>::all_;
1529
1530
1531
1532    // Gunter Winkler contributed the classes index_pair, index_pair_array,
1533    // index_triple and index_triple_array to enable inplace sort of parallel arrays.
1534
1535    template <class V>
1536    class index_pair :
1537        private boost::noncopyable,
1538        public container_reference<V> {
1539
1540        typedef index_pair<V> self_type;
1541    public:
1542        typedef typename V::size_type size_type;
1543
1544        BOOST_UBLAS_INLINE
1545        index_pair(V& v, size_type i) :
1546            container_reference<V>(v), i_(i),
1547            v1_(v.data1_[i]), v2_(v.data2_[i]),
1548            dirty_(false), is_copy_(false) {}
1549         BOOST_UBLAS_INLINE
1550        index_pair(const self_type& rhs) :
1551            container_reference<V>(rhs()), i_(0),
1552            v1_(rhs.v1_), v2_(rhs.v2_),
1553            dirty_(false), is_copy_(true) {}
1554         BOOST_UBLAS_INLINE
1555        ~index_pair() {
1556            if (dirty_ && (!is_copy_) ) {
1557                (*this)().data1_[i_] = v1_;
1558                (*this)().data2_[i_] = v2_;
1559            }
1560        }
1561
1562        BOOST_UBLAS_INLINE
1563        self_type& operator=(const self_type& rhs) {
1564            v1_ = rhs.v1_;
1565            v2_ = rhs.v2_;
1566            dirty_ = true;
1567            return *this;
1568        }
1569
1570        BOOST_UBLAS_INLINE
1571        void swap(self_type rhs) {
1572            self_type tmp(rhs);
1573            rhs = *this;
1574            *this = tmp;
1575        }
1576        BOOST_UBLAS_INLINE
1577        friend void swap(self_type lhs, self_type rhs) {
1578            lhs.swap(rhs);
1579        }
1580
1581        BOOST_UBLAS_INLINE
1582        bool equal(const self_type& rhs) const {
1583            return (v1_ == rhs.v1_);
1584        }
1585        bool less(const self_type& rhs) const {
1586            return (v1_ < rhs.v1_);
1587        }
1588        BOOST_UBLAS_INLINE
1589        friend bool operator == (const self_type& lhs, const self_type& rhs) {
1590            return lhs.equal(rhs);
1591        }
1592        BOOST_UBLAS_INLINE
1593        friend bool operator != (const self_type& lhs, const self_type& rhs) {
1594            return !lhs.equal(rhs);
1595        }
1596        BOOST_UBLAS_INLINE
1597        friend bool operator < (const self_type& lhs, const self_type& rhs) {
1598            return lhs.less(rhs);
1599        }
1600
1601    private:
1602        size_type i_;
1603        typename V::value1_type v1_;
1604        typename V::value2_type v2_;
1605        bool dirty_;
1606        bool is_copy_;
1607     };
1608
1609    template <class V1, class V2>
1610    class index_pair_array:
1611        private boost::noncopyable {
1612
1613        typedef index_pair_array<V1, V2> self_type;
1614    public:
1615        typedef typename V1::value_type value1_type;
1616        typedef typename V2::value_type value2_type;
1617
1618        typedef typename V1::size_type size_type;
1619        typedef typename V1::difference_type difference_type;
1620        typedef index_pair<self_type> value_type;
1621        // There is nothing that can be referenced directly. Always return a copy of the index_pair
1622        typedef value_type reference;
1623        typedef const value_type const_reference;
1624
1625        BOOST_UBLAS_INLINE
1626        index_pair_array(size_type size, V1& data1, V2& data2) :
1627              size_(size),data1_(data1),data2_(data2) {}
1628
1629        BOOST_UBLAS_INLINE
1630        size_type size() const {
1631            return size_;
1632        }
1633
1634        BOOST_UBLAS_INLINE
1635        const_reference operator () (size_type i) const {
1636            return value_type((*this), i);
1637        }
1638        BOOST_UBLAS_INLINE
1639        reference operator () (size_type i) {
1640            return value_type((*this), i);
1641        }
1642
1643        typedef indexed_iterator<self_type, std::random_access_iterator_tag> iterator;
1644        typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator;
1645
1646        BOOST_UBLAS_INLINE
1647        iterator begin() {
1648            return iterator( (*this), 0);
1649        }
1650        BOOST_UBLAS_INLINE
1651        iterator end() {
1652            return iterator( (*this), size());
1653        }
1654
1655        BOOST_UBLAS_INLINE
1656        const_iterator begin() const {
1657            return const_iterator( (*this), 0);
1658        }
1659        BOOST_UBLAS_INLINE
1660        const_iterator end() const {
1661            return const_iterator( (*this), size());
1662        }
1663
1664        // unnecessary function:
1665        BOOST_UBLAS_INLINE
1666        bool equal(size_type i1, size_type i2) const {
1667            return data1_[i1] == data1_[i2];
1668        }
1669        BOOST_UBLAS_INLINE
1670        bool less(size_type i1, size_type i2) const {
1671            return data1_[i1] < data1_[i2];
1672        }
1673
1674        // gives a large speedup
1675        BOOST_UBLAS_INLINE
1676        friend void iter_swap(const iterator& lhs, const iterator& rhs) {
1677            const size_type i1 = lhs.index();
1678            const size_type i2 = rhs.index();
1679            std::swap(lhs().data1_[i1], rhs().data1_[i2]);
1680            std::swap(lhs().data2_[i1], rhs().data2_[i2]);
1681        }
1682
1683    private:
1684        size_type size_;
1685        V1& data1_;
1686        V2& data2_;
1687
1688        // friend class value_type;
1689        friend class index_pair<self_type>;
1690    };
1691
1692    template <class M>
1693    class index_triple :
1694        private boost::noncopyable,
1695        public container_reference<M> {
1696
1697        typedef index_triple<M> self_type;
1698    public:
1699        typedef typename M::size_type size_type;
1700
1701        BOOST_UBLAS_INLINE
1702        index_triple(M& m, size_type i) :
1703            container_reference<M>(m), i_(i),
1704            v1_(m.data1_[i]), v2_(m.data2_[i]), v3_(m.data3_[i]),
1705            dirty_(false), is_copy_(false) {}
1706        BOOST_UBLAS_INLINE
1707        index_triple(const self_type& rhs) :
1708            container_reference<M>(rhs()), i_(0),
1709            v1_(rhs.v1_), v2_(rhs.v2_), v3_(rhs.v3_),
1710            dirty_(false), is_copy_(true) {}
1711        BOOST_UBLAS_INLINE
1712        ~index_triple() {
1713            if (dirty_ && (!is_copy_) ) {
1714                (*this)().data1_[i_] = v1_;
1715                (*this)().data2_[i_] = v2_;
1716                (*this)().data3_[i_] = v3_;
1717            }
1718        }
1719
1720        BOOST_UBLAS_INLINE
1721        self_type& operator=(const self_type& rhs) {
1722            v1_ = rhs.v1_;
1723            v2_ = rhs.v2_;
1724            v3_ = rhs.v3_;
1725            dirty_ = true;
1726            return *this;
1727        }
1728
1729        BOOST_UBLAS_INLINE
1730        void swap(self_type rhs) {
1731            self_type tmp(rhs);
1732            rhs = *this;
1733            *this = tmp;
1734        }
1735        BOOST_UBLAS_INLINE
1736        friend void swap(self_type lhs, self_type rhs) {
1737            lhs.swap(rhs);
1738        }
1739
1740        BOOST_UBLAS_INLINE
1741        bool equal(const self_type& rhs) const {
1742            return ((v1_ == rhs.v1_) && (v2_ == rhs.v2_));
1743        }
1744        BOOST_UBLAS_INLINE
1745        bool less(const self_type& rhs) const {
1746            return ((v1_ < rhs.v1_) ||
1747                    (v1_ == rhs.v1_ && v2_ < rhs.v2_));
1748        }
1749        BOOST_UBLAS_INLINE
1750        friend bool operator == (const self_type& lhs, const self_type& rhs) {
1751            return lhs.equal(rhs);
1752        }
1753        BOOST_UBLAS_INLINE
1754        friend bool operator != (const self_type& lhs, const self_type& rhs) {
1755            return !lhs.equal(rhs);
1756        }
1757        BOOST_UBLAS_INLINE
1758        friend bool operator < (const self_type& lhs, const self_type& rhs) {
1759            return lhs.less(rhs);
1760        }
1761
1762    private:
1763        size_type i_;
1764        typename M::value1_type v1_;
1765        typename M::value2_type v2_;
1766        typename M::value3_type v3_;
1767        bool dirty_;
1768        bool is_copy_;
1769    };
1770
1771    template <class V1, class V2, class V3>
1772    class index_triple_array:
1773        private boost::noncopyable {
1774
1775        typedef index_triple_array<V1, V2, V3> self_type;
1776    public:
1777        typedef typename V1::value_type value1_type;
1778        typedef typename V2::value_type value2_type;
1779        typedef typename V3::value_type value3_type;
1780
1781        typedef typename V1::size_type size_type;
1782        typedef typename V1::difference_type difference_type;
1783        typedef index_triple<self_type> value_type;
1784        // There is nothing that can be referenced directly. Always return a copy of the index_triple
1785        typedef value_type reference;
1786        typedef const value_type const_reference;
1787
1788        BOOST_UBLAS_INLINE
1789        index_triple_array(size_type size, V1& data1, V2& data2, V3& data3) :
1790              size_(size),data1_(data1),data2_(data2),data3_(data3) {}
1791
1792        BOOST_UBLAS_INLINE
1793        size_type size() const {
1794            return size_;
1795        }
1796
1797        BOOST_UBLAS_INLINE
1798        const_reference operator () (size_type i) const {
1799            return value_type((*this), i);
1800        }
1801        BOOST_UBLAS_INLINE
1802        reference operator () (size_type i) {
1803            return value_type((*this), i);
1804        }
1805
1806        typedef indexed_iterator<self_type, std::random_access_iterator_tag> iterator;
1807        typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator;
1808
1809        BOOST_UBLAS_INLINE
1810        iterator begin() {
1811            return iterator( (*this), 0);
1812        }
1813        BOOST_UBLAS_INLINE
1814        iterator end() {
1815            return iterator( (*this), size());
1816        }
1817
1818        BOOST_UBLAS_INLINE
1819        const_iterator begin() const {
1820            return const_iterator( (*this), 0);
1821        }
1822        BOOST_UBLAS_INLINE
1823        const_iterator end() const {
1824            return const_iterator( (*this), size());
1825        }
1826
1827        // unnecessary function:
1828        BOOST_UBLAS_INLINE
1829        bool equal(size_type i1, size_type i2) const {
1830            return ((data1_[i1] == data1_[i2]) && (data2_[i1] == data2_[i2]));
1831        }
1832        BOOST_UBLAS_INLINE
1833        bool less(size_type i1, size_type i2) const {
1834            return ((data1_[i1] < data1_[i2]) ||
1835                    (data1_[i1] == data1_[i2] && data2_[i1] < data2_[i2]));
1836        }
1837
1838        // gives a large speedup
1839        BOOST_UBLAS_INLINE
1840        friend void iter_swap(const iterator& lhs, const iterator& rhs) {
1841            const size_type i1 = lhs.index();
1842            const size_type i2 = rhs.index();
1843            std::swap(lhs().data1_[i1], rhs().data1_[i2]);
1844            std::swap(lhs().data2_[i1], rhs().data2_[i2]);
1845            std::swap(lhs().data3_[i1], rhs().data3_[i2]);
1846        }
1847
1848    private:
1849        size_type size_;
1850        V1& data1_;
1851        V2& data2_;
1852        V3& data3_;
1853
1854        // friend class value_type;
1855        friend class index_triple<self_type>;
1856    };
1857
1858}}}
1859
1860#endif
Note: See TracBrowser for help on using the repository browser.