2 // Copyright (c) 2000-2002
3 // Joerg Walter, Mathias Koch
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 // The authors gratefully acknowledge the support of
10 // GeNeSys mbH & Co. KG in producing this work.
13 #ifndef BOOST_UBLAS_STORAGE_H
14 #define BOOST_UBLAS_STORAGE_H
17 #ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR
18 #include <boost/shared_array.hpp>
21 #include <boost/serialization/array.hpp>
22 #include <boost/serialization/collection_size_type.hpp>
23 #include <boost/serialization/nvp.hpp>
25 #include <boost/numeric/ublas/exception.hpp>
26 #include <boost/numeric/ublas/traits.hpp>
27 #include <boost/numeric/ublas/detail/iterator.hpp>
30 namespace boost
{ namespace numeric
{ namespace ublas
{
33 // Base class for Storage Arrays - see the Barton Nackman trick
36 private nonassignable
{
40 // Unbounded array - with allocator
41 template<class T
, class ALLOC
>
42 class unbounded_array
:
43 public storage_array
<unbounded_array
<T
, ALLOC
> > {
45 typedef unbounded_array
<T
, ALLOC
> self_type
;
47 typedef ALLOC allocator_type
;
48 typedef typename
ALLOC::size_type size_type
;
49 typedef typename
ALLOC::difference_type difference_type
;
51 typedef const T
&const_reference
;
53 typedef const T
*const_pointer
;
55 typedef const_pointer const_iterator
;
56 typedef pointer iterator
;
58 // Construction and destruction
59 explicit BOOST_UBLAS_INLINE
60 unbounded_array (const ALLOC
&a
= ALLOC()):
61 alloc_ (a
), size_ (0) {
64 explicit BOOST_UBLAS_INLINE
65 unbounded_array (size_type size
, const ALLOC
&a
= ALLOC()):
66 alloc_(a
), size_ (size
) {
68 data_
= alloc_
.allocate (size_
);
69 if (! detail::has_trivial_constructor
<T
>::value
) {
70 for (pointer d
= data_
; d
!= data_
+ size_
; ++d
)
71 alloc_
.construct(d
, value_type());
77 // No value initialised, but still be default constructed
79 unbounded_array (size_type size
, const value_type
&init
, const ALLOC
&a
= ALLOC()):
80 alloc_ (a
), size_ (size
) {
82 data_
= alloc_
.allocate (size_
);
83 std::uninitialized_fill (begin(), end(), init
);
89 unbounded_array (const unbounded_array
&c
):
90 storage_array
<unbounded_array
<T
, ALLOC
> >(),
91 alloc_ (c
.alloc_
), size_ (c
.size_
) {
93 data_
= alloc_
.allocate (size_
);
94 std::uninitialized_copy (c
.begin(), c
.end(), begin());
100 ~unbounded_array () {
102 if (! detail::has_trivial_destructor
<T
>::value
) {
103 // std::_Destroy (begin(), end(), alloc_);
104 const iterator i_end
= end();
105 for (iterator i
= begin (); i
!= i_end
; ++i
) {
106 iterator_destroy (i
);
109 alloc_
.deallocate (data_
, size_
);
116 void resize_internal (const size_type size
, const value_type init
, const bool preserve
) {
118 pointer p_data
= data_
;
120 data_
= alloc_
.allocate (size
);
125 for (; di
!= data_
+ size
; ++di
) {
126 alloc_
.construct (di
, *si
);
131 for (pointer si
= p_data
; si
!= p_data
+ size_
; ++si
) {
132 alloc_
.construct (di
, *si
);
135 for (; di
!= data_
+ size
; ++di
) {
136 alloc_
.construct (di
, init
);
141 if (! detail::has_trivial_constructor
<T
>::value
) {
142 for (pointer di
= data_
; di
!= data_
+ size
; ++di
)
143 alloc_
.construct (di
, value_type());
149 if (! detail::has_trivial_destructor
<T
>::value
) {
150 for (pointer si
= p_data
; si
!= p_data
+ size_
; ++si
)
153 alloc_
.deallocate (p_data
, size_
);
163 void resize (size_type size
) {
164 resize_internal (size
, value_type (), false);
167 void resize (size_type size
, value_type init
) {
168 resize_internal (size
, init
, true);
171 // Random Access Container
173 size_type
max_size () const {
174 return ALLOC ().max_size();
178 bool empty () const {
183 size_type
size () const {
189 const_reference
operator [] (size_type i
) const {
190 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
194 reference
operator [] (size_type i
) {
195 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
201 unbounded_array
&operator = (const unbounded_array
&a
) {
204 std::copy (a
.data_
, a
.data_
+ a
.size_
, data_
);
209 unbounded_array
&assign_temporary (unbounded_array
&a
) {
216 void swap (unbounded_array
&a
) {
218 std::swap (size_
, a
.size_
);
219 std::swap (data_
, a
.data_
);
223 friend void swap (unbounded_array
&a1
, unbounded_array
&a2
) {
228 const_iterator
begin () const {
232 const_iterator
end () const {
233 return data_
+ size_
;
242 return data_
+ size_
;
246 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
247 typedef std::reverse_iterator
<iterator
> reverse_iterator
;
250 const_reverse_iterator
rbegin () const {
251 return const_reverse_iterator (end ());
254 const_reverse_iterator
rend () const {
255 return const_reverse_iterator (begin ());
258 reverse_iterator
rbegin () {
259 return reverse_iterator (end ());
262 reverse_iterator
rend () {
263 return reverse_iterator (begin ());
267 allocator_type
get_allocator () {
272 friend class boost::serialization::access
;
275 template<class Archive
>
276 void serialize(Archive
& ar
, const unsigned int version
)
278 serialization::collection_size_type
s(size_
);
279 ar
& serialization::make_nvp("size",s
);
280 if ( Archive::is_loading::value
) {
283 ar
& serialization::make_array(data_
, s
);
287 // Handle explict destroy on a (possibly indexed) iterator
289 static void iterator_destroy (iterator
&i
) {
290 (&(*i
)) -> ~value_type ();
297 // Bounded array - with allocator for size_type and difference_type
298 template<class T
, std::size_t N
, class ALLOC
>
300 public storage_array
<bounded_array
<T
, N
, ALLOC
> > {
302 typedef bounded_array
<T
, N
, ALLOC
> self_type
;
304 // No allocator_type as ALLOC is not used for allocation
305 typedef typename
ALLOC::size_type size_type
;
306 typedef typename
ALLOC::difference_type difference_type
;
307 typedef T value_type
;
308 typedef const T
&const_reference
;
309 typedef T
&reference
;
310 typedef const T
*const_pointer
;
312 typedef const_pointer const_iterator
;
313 typedef pointer iterator
;
315 // Construction and destruction
318 size_ (0) /*, data_ ()*/ { // size 0 - use bounded_vector to default construct with size N
320 explicit BOOST_UBLAS_INLINE
321 bounded_array (size_type size
):
322 size_ (size
) /*, data_ ()*/ {
323 BOOST_UBLAS_CHECK (size_
<= N
, bad_size ());
324 // data_ (an array) elements are already default constructed
327 bounded_array (size_type size
, const value_type
&init
):
328 size_ (size
) /*, data_ ()*/ {
329 BOOST_UBLAS_CHECK (size_
<= N
, bad_size ());
330 // ISSUE elements should be value constructed here, but we must fill instead as already default constructed
331 std::fill (begin(), end(), init
) ;
334 bounded_array (const bounded_array
&c
):
336 // ISSUE elements should be copy constructed here, but we must copy instead as already default constructed
337 std::copy (c
.begin(), c
.end(), begin());
342 void resize (size_type size
) {
343 BOOST_UBLAS_CHECK (size
<= N
, bad_size ());
347 void resize (size_type size
, value_type init
) {
348 BOOST_UBLAS_CHECK (size
<= N
, bad_size ());
350 std::fill (data_
+ size_
, data_
+ size
, init
);
354 // Random Access Container
356 size_type
max_size () const {
357 return ALLOC ().max_size();
361 bool empty () const {
366 size_type
size () const {
372 const_reference
operator [] (size_type i
) const {
373 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
377 reference
operator [] (size_type i
) {
378 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
384 bounded_array
&operator = (const bounded_array
&a
) {
387 std::copy (a
.data_
, a
.data_
+ a
.size_
, data_
);
392 bounded_array
&assign_temporary (bounded_array
&a
) {
399 void swap (bounded_array
&a
) {
401 std::swap (size_
, a
.size_
);
402 std::swap_ranges (data_
, data_
+ (std::max
) (size_
, a
.size_
), a
.data_
);
406 friend void swap (bounded_array
&a1
, bounded_array
&a2
) {
411 const_iterator
begin () const {
415 const_iterator
end () const {
416 return data_
+ size_
;
425 return data_
+ size_
;
429 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
430 typedef std::reverse_iterator
<iterator
> reverse_iterator
;
433 const_reverse_iterator
rbegin () const {
434 return const_reverse_iterator (end ());
437 const_reverse_iterator
rend () const {
438 return const_reverse_iterator (begin ());
441 reverse_iterator
rbegin () {
442 return reverse_iterator (end ());
445 reverse_iterator
rend () {
446 return reverse_iterator (begin ());
451 friend class boost::serialization::access
;
453 template<class Archive
>
454 void serialize(Archive
& ar
, const unsigned int version
)
456 serialization::collection_size_type
s(size_
);
457 ar
& serialization::make_nvp("size", s
);
458 if ( Archive::is_loading::value
) {
459 if (s
> N
) bad_size("too large size in bounded_array::load()\n").raise();
462 ar
& serialization::make_array(data_
, s
);
467 BOOST_UBLAS_BOUNDED_ARRAY_ALIGN value_type data_
[N
];
471 // Array adaptor with normal deep copy semantics of elements
474 public storage_array
<array_adaptor
<T
> > {
476 typedef array_adaptor
<T
> self_type
;
478 typedef std::size_t size_type
;
479 typedef std::ptrdiff_t difference_type
;
480 typedef T value_type
;
481 typedef const T
&const_reference
;
482 typedef T
&reference
;
483 typedef const T
*const_pointer
;
486 // Construction and destruction
489 size_ (0), own_ (true), data_ (new value_type
[0]) {
491 explicit BOOST_UBLAS_INLINE
492 array_adaptor (size_type size
):
493 size_ (size
), own_ (true), data_ (new value_type
[size
]) {
496 array_adaptor (size_type size
, const value_type
&init
):
497 size_ (size
), own_ (true), data_ (new value_type
[size
]) {
498 std::fill (data_
, data_
+ size_
, init
);
501 array_adaptor (size_type size
, pointer data
):
502 size_ (size
), own_ (false), data_ (data
) {}
504 array_adaptor (const array_adaptor
&a
):
505 storage_array
<self_type
> (),
506 size_ (a
.size_
), own_ (true), data_ (new value_type
[a
.size_
]) {
519 void resize_internal (size_type size
, value_type init
, bool preserve
= true) {
521 pointer data
= new value_type
[size
];
523 std::copy (data_
, data_
+ (std::min
) (size
, size_
), data
);
524 std::fill (data
+ (std::min
) (size
, size_
), data
+ size
, init
);
534 void resize_internal (size_type size
, pointer data
, value_type init
, bool preserve
= true) {
537 std::copy (data_
, data_
+ (std::min
) (size
, size_
), data
);
538 std::fill (data
+ (std::min
) (size
, size_
), data
+ size
, init
);
546 std::fill (data
+ (std::min
) (size
, size_
), data
+ size
, init
);
552 void resize (size_type size
) {
553 resize_internal (size
, value_type (), false);
556 void resize (size_type size
, value_type init
) {
557 resize_internal (size
, init
, true);
560 void resize (size_type size
, pointer data
) {
561 resize_internal (size
, data
, value_type (), false);
564 void resize (size_type size
, pointer data
, value_type init
) {
565 resize_internal (size
, data
, init
, true);
569 size_type
size () const {
575 const_reference
operator [] (size_type i
) const {
576 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
580 reference
operator [] (size_type i
) {
581 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
587 array_adaptor
&operator = (const array_adaptor
&a
) {
590 std::copy (a
.data_
, a
.data_
+ a
.size_
, data_
);
595 array_adaptor
&assign_temporary (array_adaptor
&a
) {
605 void swap (array_adaptor
&a
) {
607 std::swap (size_
, a
.size_
);
608 std::swap (own_
, a
.own_
);
609 std::swap (data_
, a
.data_
);
613 friend void swap (array_adaptor
&a1
, array_adaptor
&a2
) {
617 // Iterators simply are pointers.
619 typedef const_pointer const_iterator
;
622 const_iterator
begin () const {
626 const_iterator
end () const {
627 return data_
+ size_
;
630 typedef pointer iterator
;
638 return data_
+ size_
;
642 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
643 typedef std::reverse_iterator
<iterator
> reverse_iterator
;
646 const_reverse_iterator
rbegin () const {
647 return const_reverse_iterator (end ());
650 const_reverse_iterator
rend () const {
651 return const_reverse_iterator (begin ());
654 reverse_iterator
rbegin () {
655 return reverse_iterator (end ());
658 reverse_iterator
rend () {
659 return reverse_iterator (begin ());
668 #ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR
669 // Array adaptor with shallow (reference) copy semantics of elements.
670 // shared_array is used to maintain reference counts.
671 // This class breaks the normal copy semantics for a storage container and is very dangerous!
673 class shallow_array_adaptor
:
674 public storage_array
<shallow_array_adaptor
<T
> > {
676 typedef shallow_array_adaptor
<T
> self_type
;
680 typedef void result_type
;
681 typedef TT
*argument_type
;
684 result_type
operator () (argument_type x
) {}
688 typedef std::size_t size_type
;
689 typedef std::ptrdiff_t difference_type
;
690 typedef T value_type
;
691 typedef const T
&const_reference
;
692 typedef T
&reference
;
693 typedef const T
*const_pointer
;
696 // Construction and destruction
698 shallow_array_adaptor ():
699 size_ (0), own_ (true), data_ (new value_type
[0]) {
701 explicit BOOST_UBLAS_INLINE
702 shallow_array_adaptor (size_type size
):
703 size_ (size
), own_ (true), data_ (new value_type
[size
]) {
706 shallow_array_adaptor (size_type size
, const value_type
&init
):
707 size_ (size
), own_ (true), data_ (new value_type
[size
]) {
708 std::fill (data_
.get (), data_
.get () + size_
, init
);
711 shallow_array_adaptor (size_type size
, pointer data
):
712 size_ (size
), own_ (false), data_ (data
, leaker
<value_type
> ()) {}
715 shallow_array_adaptor (const shallow_array_adaptor
&a
):
716 storage_array
<self_type
> (),
717 size_ (a
.size_
), own_ (a
.own_
), data_ (a
.data_
) {}
720 ~shallow_array_adaptor () {
726 void resize_internal (size_type size
, value_type init
, bool preserve
= true) {
728 shared_array
<value_type
> data (new value_type
[size
]);
730 std::copy (data_
.get (), data_
.get () + (std::min
) (size
, size_
), data
.get ());
731 std::fill (data
.get () + (std::min
) (size
, size_
), data
.get () + size
, init
);
738 void resize_internal (size_type size
, pointer data
, value_type init
, bool preserve
= true) {
740 std::copy (data_
.get (), data_
.get () + (std::min
) (size
, size_
), data
);
741 std::fill (data
+ (std::min
) (size
, size_
), data
+ size
, init
);
748 void resize (size_type size
) {
749 resize_internal (size
, value_type (), false);
752 void resize (size_type size
, value_type init
) {
753 resize_internal (size
, init
, true);
756 void resize (size_type size
, pointer data
) {
757 resize_internal (size
, data
, value_type (), false);
760 void resize (size_type size
, pointer data
, value_type init
) {
761 resize_internal (size
, data
, init
, true);
765 size_type
size () const {
771 const_reference
operator [] (size_type i
) const {
772 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
776 reference
operator [] (size_type i
) {
777 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
783 shallow_array_adaptor
&operator = (const shallow_array_adaptor
&a
) {
786 std::copy (a
.data_
.get (), a
.data_
.get () + a
.size_
, data_
.get ());
791 shallow_array_adaptor
&assign_temporary (shallow_array_adaptor
&a
) {
801 void swap (shallow_array_adaptor
&a
) {
803 std::swap (size_
, a
.size_
);
804 std::swap (own_
, a
.own_
);
805 std::swap (data_
, a
.data_
);
809 friend void swap (shallow_array_adaptor
&a1
, shallow_array_adaptor
&a2
) {
813 // Iterators simply are pointers.
815 typedef const_pointer const_iterator
;
818 const_iterator
begin () const {
822 const_iterator
end () const {
823 return data_
.get () + size_
;
826 typedef pointer iterator
;
834 return data_
.get () + size_
;
838 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
839 typedef std::reverse_iterator
<iterator
> reverse_iterator
;
842 const_reverse_iterator
rbegin () const {
843 return const_reverse_iterator (end ());
846 const_reverse_iterator
rend () const {
847 return const_reverse_iterator (begin ());
850 reverse_iterator
rbegin () {
851 return reverse_iterator (end ());
854 reverse_iterator
rend () {
855 return reverse_iterator (begin ());
861 shared_array
<value_type
> data_
;
868 template <class Z
, class D
>
870 typedef basic_range
<Z
, D
> self_type
;
873 typedef D difference_type
;
874 typedef size_type value_type
;
875 typedef value_type const_reference
;
876 typedef const_reference reference
;
877 typedef const value_type
*const_pointer
;
878 typedef value_type
*pointer
;
880 // Construction and destruction
883 start_ (0), size_ (0) {}
885 basic_range (size_type start
, size_type stop
):
886 start_ (start
), size_ (stop
- start
) {
887 BOOST_UBLAS_CHECK (start_
<= stop
, bad_index ());
891 size_type
start () const {
895 size_type
size () const {
899 // Random Access Container
901 size_type
max_size () const {
906 bool empty () const {
912 const_reference
operator () (size_type i
) const {
913 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
919 basic_range
compose (const basic_range
&r
) const {
920 return basic_range (start_
+ r
.start_
, start_
+ r
.start_
+ r
.size_
);
925 bool operator == (const basic_range
&r
) const {
926 return start_
== r
.start_
&& size_
== r
.size_
;
929 bool operator != (const basic_range
&r
) const {
930 return ! (*this == r
);
936 typedef size_type const_subiterator_type
;
939 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
940 typedef indexed_const_iterator
<self_type
, std::random_access_iterator_tag
> const_iterator
;
942 class const_iterator
:
943 public container_const_reference
<basic_range
>,
944 public random_access_iterator_base
<std::random_access_iterator_tag
,
945 const_iterator
, value_type
> {
947 typedef typename
basic_range::value_type value_type
;
948 typedef typename
basic_range::difference_type difference_type
;
949 typedef typename
basic_range::const_reference reference
;
950 typedef typename
basic_range::const_pointer pointer
;
952 // Construction and destruction
955 container_const_reference
<basic_range
> (), it_ () {}
957 const_iterator (const basic_range
&r
, const const_subiterator_type
&it
):
958 container_const_reference
<basic_range
> (r
), it_ (it
) {}
962 const_iterator
&operator ++ () {
967 const_iterator
&operator -- () {
968 BOOST_UBLAS_CHECK (it_
> 0, bad_index ());
973 const_iterator
&operator += (difference_type n
) {
974 BOOST_UBLAS_CHECK (n
>= 0 || it_
>= size_type(-n
), bad_index ());
979 const_iterator
&operator -= (difference_type n
) {
980 BOOST_UBLAS_CHECK (n
<= 0 || it_
>= size_type(n
), bad_index ());
985 difference_type
operator - (const const_iterator
&it
) const {
991 const_reference
operator * () const {
992 BOOST_UBLAS_CHECK ((*this) ().start () <= it_
, bad_index ());
993 BOOST_UBLAS_CHECK (it_
< (*this) ().start () + (*this) ().size (), bad_index ());
998 const_reference
operator [] (difference_type n
) const {
1004 size_type
index () const {
1005 BOOST_UBLAS_CHECK ((*this) ().start () <= it_
, bad_index ());
1006 BOOST_UBLAS_CHECK (it_
< (*this) ().start () + (*this) ().size (), bad_index ());
1007 return it_
- (*this) ().start ();
1012 const_iterator
&operator = (const const_iterator
&it
) {
1013 // Comeau recommends...
1014 this->assign (&it ());
1021 bool operator == (const const_iterator
&it
) const {
1022 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
1023 return it_
== it
.it_
;
1026 bool operator < (const const_iterator
&it
) const {
1027 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
1028 return it_
< it
.it_
;
1032 const_subiterator_type it_
;
1037 const_iterator
begin () const {
1038 return const_iterator (*this, start_
);
1041 const_iterator
end () const {
1042 return const_iterator (*this, start_
+ size_
);
1046 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
1049 const_reverse_iterator
rbegin () const {
1050 return const_reverse_iterator (end ());
1053 const_reverse_iterator
rend () const {
1054 return const_reverse_iterator (begin ());
1058 basic_range
preprocess (size_type size
) const {
1061 return basic_range (0, size
);
1065 const basic_range
&all () {
1072 static const basic_range all_
;
1075 template <class Z
, class D
>
1076 const basic_range
<Z
,D
> basic_range
<Z
,D
>::all_ (0, size_type (-1));
1080 template <class Z
, class D
>
1082 typedef basic_slice
<Z
, D
> self_type
;
1084 typedef Z size_type
;
1085 typedef D difference_type
;
1086 typedef size_type value_type
;
1087 typedef value_type const_reference
;
1088 typedef const_reference reference
;
1089 typedef const value_type
*const_pointer
;
1090 typedef value_type
*pointer
;
1092 // Construction and destruction
1095 start_ (0), stride_ (0), size_ (0) {}
1097 basic_slice (size_type start
, difference_type stride
, size_type size
):
1098 start_ (start
), stride_ (stride
), size_ (size
) {}
1101 size_type
start () const {
1105 difference_type
stride () const {
1109 size_type
size () const {
1113 // Random Access Container
1115 size_type
max_size () const {
1120 bool empty () const {
1126 const_reference
operator () (size_type i
) const {
1127 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
1128 BOOST_UBLAS_CHECK (stride_
>= 0 || start_
>= i
* -stride_
, bad_index ());
1129 return start_
+ i
* stride_
;
1134 basic_slice
compose (const basic_range
<size_type
, difference_type
> &r
) const {
1135 BOOST_UBLAS_CHECK (stride_
>=0 || start_
>= -stride_
* r
.start(), bad_index ());
1136 return basic_slice (start_
+ stride_
* r
.start (), stride_
, r
.size ());
1139 basic_slice
compose (const basic_slice
&s
) const {
1140 BOOST_UBLAS_CHECK (stride_
>=0 || start_
>= -stride_
* s
.start_
, bad_index ());
1141 return basic_slice (start_
+ stride_
* s
.start_
, stride_
* s
.stride_
, s
.size_
);
1146 bool operator == (const basic_slice
&s
) const {
1147 return start_
== s
.start_
&& stride_
== s
.stride_
&& size_
== s
.size_
;
1150 bool operator != (const basic_slice
&s
) const {
1151 return ! (*this == s
);
1157 typedef size_type const_subiterator_type
;
1160 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1161 typedef indexed_const_iterator
<self_type
, std::random_access_iterator_tag
> const_iterator
;
1163 class const_iterator
:
1164 public container_const_reference
<basic_slice
>,
1165 public random_access_iterator_base
<std::random_access_iterator_tag
,
1166 const_iterator
, value_type
> {
1168 typedef typename
basic_slice::value_type value_type
;
1169 typedef typename
basic_slice::difference_type difference_type
;
1170 typedef typename
basic_slice::const_reference reference
;
1171 typedef typename
basic_slice::const_pointer pointer
;
1173 // Construction and destruction
1176 container_const_reference
<basic_slice
> (), it_ () {}
1178 const_iterator (const basic_slice
&s
, const const_subiterator_type
&it
):
1179 container_const_reference
<basic_slice
> (s
), it_ (it
) {}
1183 const_iterator
&operator ++ () {
1188 const_iterator
&operator -- () {
1189 BOOST_UBLAS_CHECK (it_
> 0, bad_index ());
1194 const_iterator
&operator += (difference_type n
) {
1195 BOOST_UBLAS_CHECK (n
>= 0 || it_
>= size_type(-n
), bad_index ());
1200 const_iterator
&operator -= (difference_type n
) {
1201 BOOST_UBLAS_CHECK (n
<= 0 || it_
>= size_type(n
), bad_index ());
1206 difference_type
operator - (const const_iterator
&it
) const {
1207 return it_
- it
.it_
;
1212 const_reference
operator * () const {
1213 BOOST_UBLAS_CHECK (it_
< (*this) ().size (), bad_index ());
1214 return (*this) ().start () + it_
* (*this) ().stride ();
1218 const_reference
operator [] (difference_type n
) const {
1219 return *(*this + n
);
1224 size_type
index () const {
1225 BOOST_UBLAS_CHECK (it_
< (*this) ().size (), bad_index ());
1231 const_iterator
&operator = (const const_iterator
&it
) {
1232 // Comeau recommends...
1233 this->assign (&it ());
1240 bool operator == (const const_iterator
&it
) const {
1241 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
1242 return it_
== it
.it_
;
1245 bool operator < (const const_iterator
&it
) const {
1246 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
1247 return it_
< it
.it_
;
1251 const_subiterator_type it_
;
1256 const_iterator
begin () const {
1257 return const_iterator (*this, 0);
1260 const_iterator
end () const {
1261 return const_iterator (*this, size_
);
1265 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
1268 const_reverse_iterator
rbegin () const {
1269 return const_reverse_iterator (end ());
1272 const_reverse_iterator
rend () const {
1273 return const_reverse_iterator (begin ());
1277 basic_slice
preprocess (size_type size
) const {
1280 return basic_slice (0, 1, size
);
1284 const basic_slice
&all () {
1290 difference_type stride_
;
1292 static const basic_slice all_
;
1295 template <class Z
, class D
>
1296 const basic_slice
<Z
,D
> basic_slice
<Z
,D
>::all_ (0, 1, size_type (-1));
1299 // Indirect array class
1301 class indirect_array
{
1302 typedef indirect_array
<A
> self_type
;
1304 typedef A array_type
;
1305 typedef const A const_array_type
;
1306 typedef typename
A::size_type size_type
;
1307 typedef typename
A::difference_type difference_type
;
1308 typedef typename
A::value_type value_type
;
1309 typedef typename
A::const_reference const_reference
;
1310 typedef typename
A::reference reference
;
1311 typedef typename
A::const_pointer const_pointer
;
1312 typedef typename
A::pointer pointer
;
1314 // Construction and destruction
1317 size_ (), data_ () {}
1318 explicit BOOST_UBLAS_INLINE
1319 indirect_array (size_type size
):
1320 size_ (size
), data_ (size
) {}
1322 indirect_array (size_type size
, const array_type
&data
):
1323 size_ (size
), data_ (data
) {}
1325 indirect_array (pointer start
, pointer stop
):
1326 size_ (stop
- start
), data_ (stop
- start
) {
1327 std::copy (start
, stop
, data_
.begin ());
1331 size_type
size () const {
1335 const_array_type
data () const {
1339 array_type
data () {
1343 // Random Access Container
1345 size_type
max_size () const {
1350 bool empty () const {
1351 return data_
.size () == 0;
1356 const_reference
operator () (size_type i
) const {
1357 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
1361 reference
operator () (size_type i
) {
1362 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
1367 const_reference
operator [] (size_type i
) const {
1371 reference
operator [] (size_type i
) {
1377 indirect_array
compose (const basic_range
<size_type
, difference_type
> &r
) const {
1378 BOOST_UBLAS_CHECK (r
.start () + r
.size () <= size_
, bad_size ());
1379 array_type
data (r
.size ());
1380 for (size_type i
= 0; i
< r
.size (); ++ i
)
1381 data
[i
] = data_
[r
.start () + i
];
1382 return indirect_array (r
.size (), data
);
1385 indirect_array
compose (const basic_slice
<size_type
, difference_type
> &s
) const {
1386 BOOST_UBLAS_CHECK (s
.start () + s
.stride () * (s
.size () - (s
.size () > 0)) <= size (), bad_size ());
1387 array_type
data (s
.size ());
1388 for (size_type i
= 0; i
< s
.size (); ++ i
)
1389 data
[i
] = data_
[s
.start () + s
.stride () * i
];
1390 return indirect_array (s
.size (), data
);
1393 indirect_array
compose (const indirect_array
&ia
) const {
1394 array_type
data (ia
.size_
);
1395 for (size_type i
= 0; i
< ia
.size_
; ++ i
) {
1396 BOOST_UBLAS_CHECK (ia
.data_
[i
] <= size_
, bad_size ());
1397 data
[i
] = data_
[ia
.data_
[i
]];
1399 return indirect_array (ia
.size_
, data
);
1405 bool operator == (const indirect_array
<OA
> &ia
) const {
1406 if (size_
!= ia
.size_
)
1408 for (size_type i
= 0; i
< BOOST_UBLAS_SAME (size_
, ia
.size_
); ++ i
)
1409 if (data_
[i
] != ia
.data_
[i
])
1415 bool operator != (const indirect_array
<OA
> &ia
) const {
1416 return ! (*this == ia
);
1421 // Use a index difference
1422 typedef difference_type const_subiterator_type
;
1425 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1426 typedef indexed_const_iterator
<indirect_array
, std::random_access_iterator_tag
> const_iterator
;
1428 class const_iterator
:
1429 public container_const_reference
<indirect_array
>,
1430 public random_access_iterator_base
<std::random_access_iterator_tag
,
1431 const_iterator
, value_type
> {
1433 typedef typename
indirect_array::value_type value_type
;
1434 typedef typename
indirect_array::difference_type difference_type
;
1435 typedef typename
indirect_array::const_reference reference
;
1436 typedef typename
indirect_array::const_pointer pointer
;
1438 // Construction and destruction
1441 container_const_reference
<indirect_array
> (), it_ () {}
1443 const_iterator (const indirect_array
&ia
, const const_subiterator_type
&it
):
1444 container_const_reference
<indirect_array
> (ia
), it_ (it
) {}
1448 const_iterator
&operator ++ () {
1453 const_iterator
&operator -- () {
1458 const_iterator
&operator += (difference_type n
) {
1463 const_iterator
&operator -= (difference_type n
) {
1468 difference_type
operator - (const const_iterator
&it
) const {
1469 return it_
- it
.it_
;
1474 const_reference
operator * () const {
1475 return (*this) () (it_
);
1479 const_reference
operator [] (difference_type n
) const {
1480 return *(*this + n
);
1485 size_type
index () const {
1491 const_iterator
&operator = (const const_iterator
&it
) {
1492 // Comeau recommends...
1493 this->assign (&it ());
1500 bool operator == (const const_iterator
&it
) const {
1501 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
1502 return it_
== it
.it_
;
1505 bool operator < (const const_iterator
&it
) const {
1506 BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
1507 return it_
< it
.it_
;
1511 const_subiterator_type it_
;
1516 const_iterator
begin () const {
1517 return const_iterator (*this, 0);
1520 const_iterator
end () const {
1521 return const_iterator (*this, size_
);
1525 typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
;
1528 const_reverse_iterator
rbegin () const {
1529 return const_reverse_iterator (end ());
1532 const_reverse_iterator
rend () const {
1533 return const_reverse_iterator (begin ());
1537 indirect_array
preprocess (size_type size
) const {
1540 indirect_array
ia (size
);
1541 for (size_type i
= 0; i
< size
; ++ i
)
1547 const indirect_array
&all () {
1554 static const indirect_array all_
;
1558 const indirect_array
<A
> indirect_array
<A
>::all_
;
1562 // Gunter Winkler contributed the classes index_pair, index_pair_array,
1563 // index_triple and index_triple_array to enable inplace sort of parallel arrays.
1567 private boost::noncopyable
,
1568 public container_reference
<V
> {
1570 typedef index_pair
<V
> self_type
;
1572 typedef typename
V::size_type size_type
;
1575 index_pair(V
& v
, size_type i
) :
1576 container_reference
<V
>(v
), i_(i
),
1577 v1_(v
.data1_
[i
]), v2_(v
.data2_
[i
]),
1578 dirty_(false), is_copy_(false) {}
1580 index_pair(const self_type
& rhs
) :
1581 container_reference
<V
>(rhs()), i_(0),
1582 v1_(rhs
.v1_
), v2_(rhs
.v2_
),
1583 dirty_(false), is_copy_(true) {}
1586 if (dirty_
&& (!is_copy_
) ) {
1587 (*this)().data1_
[i_
] = v1_
;
1588 (*this)().data2_
[i_
] = v2_
;
1593 self_type
& operator=(const self_type
& rhs
) {
1601 void swap(self_type rhs
) {
1607 friend void swap(self_type lhs
, self_type rhs
) {
1612 bool equal(const self_type
& rhs
) const {
1613 return (v1_
== rhs
.v1_
);
1616 bool less(const self_type
& rhs
) const {
1617 return (v1_
< rhs
.v1_
);
1620 friend bool operator == (const self_type
& lhs
, const self_type
& rhs
) {
1621 return lhs
.equal(rhs
);
1624 friend bool operator != (const self_type
& lhs
, const self_type
& rhs
) {
1625 return !lhs
.equal(rhs
);
1628 friend bool operator < (const self_type
& lhs
, const self_type
& rhs
) {
1629 return lhs
.less(rhs
);
1632 friend bool operator >= (const self_type
& lhs
, const self_type
& rhs
) {
1633 return !lhs
.less(rhs
);
1636 friend bool operator > (const self_type
& lhs
, const self_type
& rhs
) {
1637 return rhs
.less(lhs
);
1640 friend bool operator <= (const self_type
& lhs
, const self_type
& rhs
) {
1641 return !rhs
.less(lhs
);
1646 typename
V::value1_type v1_
;
1647 typename
V::value2_type v2_
;
1652 template <class V1
, class V2
>
1653 class index_pair_array
:
1654 private boost::noncopyable
{
1656 typedef index_pair_array
<V1
, V2
> self_type
;
1658 typedef typename
V1::value_type value1_type
;
1659 typedef typename
V2::value_type value2_type
;
1661 typedef typename
V1::size_type size_type
;
1662 typedef typename
V1::difference_type difference_type
;
1663 typedef index_pair
<self_type
> value_type
;
1664 // There is nothing that can be referenced directly. Always return a copy of the index_pair
1665 typedef value_type reference
;
1666 typedef const value_type const_reference
;
1669 index_pair_array(size_type size
, V1
& data1
, V2
& data2
) :
1670 size_(size
),data1_(data1
),data2_(data2
) {}
1673 size_type
size() const {
1678 const_reference
operator () (size_type i
) const {
1679 return value_type((*this), i
);
1682 reference
operator () (size_type i
) {
1683 return value_type((*this), i
);
1686 typedef indexed_iterator
<self_type
, std::random_access_iterator_tag
> iterator
;
1687 typedef indexed_const_iterator
<self_type
, std::random_access_iterator_tag
> const_iterator
;
1691 return iterator( (*this), 0);
1695 return iterator( (*this), size());
1699 const_iterator
begin() const {
1700 return const_iterator( (*this), 0);
1703 const_iterator
end() const {
1704 return const_iterator( (*this), size());
1707 // unnecessary function:
1709 bool equal(size_type i1
, size_type i2
) const {
1710 return data1_
[i1
] == data1_
[i2
];
1713 bool less(size_type i1
, size_type i2
) const {
1714 return data1_
[i1
] < data1_
[i2
];
1717 // gives a large speedup
1719 friend void iter_swap(const iterator
& lhs
, const iterator
& rhs
) {
1720 const size_type i1
= lhs
.index();
1721 const size_type i2
= rhs
.index();
1722 std::swap(lhs().data1_
[i1
], rhs().data1_
[i2
]);
1723 std::swap(lhs().data2_
[i1
], rhs().data2_
[i2
]);
1731 // friend class value_type;
1732 friend class index_pair
<self_type
>;
1736 class index_triple
:
1737 private boost::noncopyable
,
1738 public container_reference
<M
> {
1740 typedef index_triple
<M
> self_type
;
1742 typedef typename
M::size_type size_type
;
1745 index_triple(M
& m
, size_type i
) :
1746 container_reference
<M
>(m
), i_(i
),
1747 v1_(m
.data1_
[i
]), v2_(m
.data2_
[i
]), v3_(m
.data3_
[i
]),
1748 dirty_(false), is_copy_(false) {}
1750 index_triple(const self_type
& rhs
) :
1751 container_reference
<M
>(rhs()), i_(0),
1752 v1_(rhs
.v1_
), v2_(rhs
.v2_
), v3_(rhs
.v3_
),
1753 dirty_(false), is_copy_(true) {}
1756 if (dirty_
&& (!is_copy_
) ) {
1757 (*this)().data1_
[i_
] = v1_
;
1758 (*this)().data2_
[i_
] = v2_
;
1759 (*this)().data3_
[i_
] = v3_
;
1764 self_type
& operator=(const self_type
& rhs
) {
1773 void swap(self_type rhs
) {
1779 friend void swap(self_type lhs
, self_type rhs
) {
1784 bool equal(const self_type
& rhs
) const {
1785 return ((v1_
== rhs
.v1_
) && (v2_
== rhs
.v2_
));
1788 bool less(const self_type
& rhs
) const {
1789 return ((v1_
< rhs
.v1_
) ||
1790 (v1_
== rhs
.v1_
&& v2_
< rhs
.v2_
));
1793 friend bool operator == (const self_type
& lhs
, const self_type
& rhs
) {
1794 return lhs
.equal(rhs
);
1797 friend bool operator != (const self_type
& lhs
, const self_type
& rhs
) {
1798 return !lhs
.equal(rhs
);
1801 friend bool operator < (const self_type
& lhs
, const self_type
& rhs
) {
1802 return lhs
.less(rhs
);
1805 friend bool operator >= (const self_type
& lhs
, const self_type
& rhs
) {
1806 return !lhs
.less(rhs
);
1809 friend bool operator > (const self_type
& lhs
, const self_type
& rhs
) {
1810 return rhs
.less(lhs
);
1813 friend bool operator <= (const self_type
& lhs
, const self_type
& rhs
) {
1814 return !rhs
.less(lhs
);
1819 typename
M::value1_type v1_
;
1820 typename
M::value2_type v2_
;
1821 typename
M::value3_type v3_
;
1826 template <class V1
, class V2
, class V3
>
1827 class index_triple_array
:
1828 private boost::noncopyable
{
1830 typedef index_triple_array
<V1
, V2
, V3
> self_type
;
1832 typedef typename
V1::value_type value1_type
;
1833 typedef typename
V2::value_type value2_type
;
1834 typedef typename
V3::value_type value3_type
;
1836 typedef typename
V1::size_type size_type
;
1837 typedef typename
V1::difference_type difference_type
;
1838 typedef index_triple
<self_type
> value_type
;
1839 // There is nothing that can be referenced directly. Always return a copy of the index_triple
1840 typedef value_type reference
;
1841 typedef const value_type const_reference
;
1844 index_triple_array(size_type size
, V1
& data1
, V2
& data2
, V3
& data3
) :
1845 size_(size
),data1_(data1
),data2_(data2
),data3_(data3
) {}
1848 size_type
size() const {
1853 const_reference
operator () (size_type i
) const {
1854 return value_type((*this), i
);
1857 reference
operator () (size_type i
) {
1858 return value_type((*this), i
);
1861 typedef indexed_iterator
<self_type
, std::random_access_iterator_tag
> iterator
;
1862 typedef indexed_const_iterator
<self_type
, std::random_access_iterator_tag
> const_iterator
;
1866 return iterator( (*this), 0);
1870 return iterator( (*this), size());
1874 const_iterator
begin() const {
1875 return const_iterator( (*this), 0);
1878 const_iterator
end() const {
1879 return const_iterator( (*this), size());
1882 // unnecessary function:
1884 bool equal(size_type i1
, size_type i2
) const {
1885 return ((data1_
[i1
] == data1_
[i2
]) && (data2_
[i1
] == data2_
[i2
]));
1888 bool less(size_type i1
, size_type i2
) const {
1889 return ((data1_
[i1
] < data1_
[i2
]) ||
1890 (data1_
[i1
] == data1_
[i2
] && data2_
[i1
] < data2_
[i2
]));
1893 // gives a large speedup
1895 friend void iter_swap(const iterator
& lhs
, const iterator
& rhs
) {
1896 const size_type i1
= lhs
.index();
1897 const size_type i2
= rhs
.index();
1898 std::swap(lhs().data1_
[i1
], rhs().data1_
[i2
]);
1899 std::swap(lhs().data2_
[i1
], rhs().data2_
[i2
]);
1900 std::swap(lhs().data3_
[i1
], rhs().data3_
[i2
]);
1909 // friend class value_type;
1910 friend class index_triple
<self_type
>;