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_VECTOR_SPARSE_
14 #define _BOOST_UBLAS_VECTOR_SPARSE_
16 #include <boost/numeric/ublas/storage_sparse.hpp>
17 #include <boost/numeric/ublas/vector_expression.hpp>
18 #include <boost/numeric/ublas/detail/vector_assign.hpp>
19 #if BOOST_UBLAS_TYPE_CHECK
20 #include <boost/numeric/ublas/vector.hpp>
23 // Iterators based on ideas of Jeremy Siek
25 namespace boost
{ namespace numeric
{ namespace ublas
{
27 #ifdef BOOST_UBLAS_STRICT_VECTOR_SPARSE
30 class sparse_vector_element
:
31 public container_reference
<V
> {
33 typedef V vector_type
;
34 typedef typename
V::size_type size_type
;
35 typedef typename
V::value_type value_type
;
36 typedef const value_type
&const_reference
;
37 typedef value_type
*pointer
;
40 // Proxied element operations
42 pointer p
= (*this) ().find_element (i_
);
46 d_
= value_type
/*zero*/();
49 void set (const value_type
&s
) const {
50 pointer p
= (*this) ().find_element (i_
);
52 (*this) ().insert_element (i_
, s
);
58 // Construction and destruction
59 sparse_vector_element (vector_type
&v
, size_type i
):
60 container_reference
<vector_type
> (v
), i_ (i
) {
63 sparse_vector_element (const sparse_vector_element
&p
):
64 container_reference
<vector_type
> (p
), i_ (p
.i_
) {}
66 ~sparse_vector_element () {
71 sparse_vector_element
&operator = (const sparse_vector_element
&p
) {
72 // Overide the implict copy assignment
79 sparse_vector_element
&operator = (const D
&d
) {
85 sparse_vector_element
&operator += (const D
&d
) {
93 sparse_vector_element
&operator -= (const D
&d
) {
101 sparse_vector_element
&operator *= (const D
&d
) {
109 sparse_vector_element
&operator /= (const D
&d
) {
119 bool operator == (const D
&d
) const {
125 bool operator != (const D
&d
) const {
130 // Conversion - weak link in proxy as d_ is not a perfect alias for the element
132 operator const_reference () const {
137 // Conversion to reference - may be invalidated
139 value_type
& ref () const {
140 const pointer p
= (*this) ().find_element (i_
);
142 return (*this) ().insert_element (i_
, value_type
/*zero*/());
149 mutable value_type d_
;
153 * Generalise explicit reference access
157 struct element_reference
{
158 typedef R
& reference
;
159 static reference
get_reference (reference r
)
165 struct element_reference
<sparse_vector_element
<V
> > {
166 typedef typename
V::value_type
& reference
;
167 static reference
get_reference (const sparse_vector_element
<V
>& sve
)
174 typename
detail::element_reference
<VER
>::reference
ref (VER
& ver
) {
175 return detail::element_reference
<VER
>::get_reference (ver
);
178 typename
detail::element_reference
<VER
>::reference
ref (const VER
& ver
) {
179 return detail::element_reference
<VER
>::get_reference (ver
);
184 struct type_traits
<sparse_vector_element
<V
> > {
185 typedef typename
V::value_type element_type
;
186 typedef type_traits
<sparse_vector_element
<V
> > self_type
;
187 typedef typename type_traits
<element_type
>::value_type value_type
;
188 typedef typename type_traits
<element_type
>::const_reference const_reference
;
189 typedef sparse_vector_element
<V
> reference
;
190 typedef typename type_traits
<element_type
>::real_type real_type
;
191 typedef typename type_traits
<element_type
>::precision_type precision_type
;
193 static const unsigned plus_complexity
= type_traits
<element_type
>::plus_complexity
;
194 static const unsigned multiplies_complexity
= type_traits
<element_type
>::multiplies_complexity
;
198 real_type
real (const_reference t
) {
199 return type_traits
<element_type
>::real (t
);
203 real_type
imag (const_reference t
) {
204 return type_traits
<element_type
>::imag (t
);
208 value_type
conj (const_reference t
) {
209 return type_traits
<element_type
>::conj (t
);
214 real_type
type_abs (const_reference t
) {
215 return type_traits
<element_type
>::type_abs (t
);
219 value_type
type_sqrt (const_reference t
) {
220 return type_traits
<element_type
>::type_sqrt (t
);
225 real_type
norm_1 (const_reference t
) {
226 return type_traits
<element_type
>::norm_1 (t
);
230 real_type
norm_2 (const_reference t
) {
231 return type_traits
<element_type
>::norm_2 (t
);
235 real_type
norm_inf (const_reference t
) {
236 return type_traits
<element_type
>::norm_inf (t
);
241 bool equals (const_reference t1
, const_reference t2
) {
242 return type_traits
<element_type
>::equals (t1
, t2
);
246 template<class V1
, class T2
>
247 struct promote_traits
<sparse_vector_element
<V1
>, T2
> {
248 typedef typename promote_traits
<typename sparse_vector_element
<V1
>::value_type
, T2
>::promote_type promote_type
;
250 template<class T1
, class V2
>
251 struct promote_traits
<T1
, sparse_vector_element
<V2
> > {
252 typedef typename promote_traits
<T1
, typename sparse_vector_element
<V2
>::value_type
>::promote_type promote_type
;
254 template<class V1
, class V2
>
255 struct promote_traits
<sparse_vector_element
<V1
>, sparse_vector_element
<V2
> > {
256 typedef typename promote_traits
<typename sparse_vector_element
<V1
>::value_type
,
257 typename sparse_vector_element
<V2
>::value_type
>::promote_type promote_type
;
263 // Index map based sparse vector class
264 template<class T
, class A
>
266 public vector_container
<mapped_vector
<T
, A
> > {
268 typedef T
&true_reference
;
270 typedef const T
*const_pointer
;
271 typedef mapped_vector
<T
, A
> self_type
;
273 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
274 using vector_container
<self_type
>::operator ();
276 typedef typename
A::size_type size_type
;
277 typedef typename
A::difference_type difference_type
;
278 typedef T value_type
;
279 typedef A array_type
;
280 typedef const value_type
&const_reference
;
281 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
282 typedef typename
detail::map_traits
<A
,T
>::reference reference
;
284 typedef sparse_vector_element
<self_type
> reference
;
286 typedef const vector_reference
<const self_type
> const_closure_type
;
287 typedef vector_reference
<self_type
> closure_type
;
288 typedef self_type vector_temporary_type
;
289 typedef sparse_tag storage_category
;
291 // Construction and destruction
294 vector_container
<self_type
> (),
295 size_ (0), data_ () {}
297 mapped_vector (size_type size
, size_type non_zeros
= 0):
298 vector_container
<self_type
> (),
299 size_ (size
), data_ () {
300 detail::map_reserve (data(), restrict_capacity (non_zeros
));
303 mapped_vector (const mapped_vector
&v
):
304 vector_container
<self_type
> (),
305 size_ (v
.size_
), data_ (v
.data_
) {}
308 mapped_vector (const vector_expression
<AE
> &ae
, size_type non_zeros
= 0):
309 vector_container
<self_type
> (),
310 size_ (ae ().size ()), data_ () {
311 detail::map_reserve (data(), restrict_capacity (non_zeros
));
312 vector_assign
<scalar_assign
> (*this, ae
);
317 size_type
size () const {
321 size_type
nnz_capacity () const {
322 return detail::map_capacity (data ());
325 size_type
nnz () const {
326 return data (). size ();
331 const array_type
&data () const {
335 array_type
&data () {
342 size_type
restrict_capacity (size_type non_zeros
) const {
343 non_zeros
= (std::min
) (non_zeros
, size_
);
348 void resize (size_type size
, bool preserve
= true) {
351 data ().erase (data ().lower_bound(size_
), data ().end());
360 void reserve (size_type non_zeros
= 0, bool preserve
= true) {
361 detail::map_reserve (data (), restrict_capacity (non_zeros
));
366 pointer
find_element (size_type i
) {
367 return const_cast<pointer
> (const_cast<const self_type
&>(*this).find_element (i
));
370 const_pointer
find_element (size_type i
) const {
371 const_subiterator_type
it (data ().find (i
));
372 if (it
== data ().end ())
374 BOOST_UBLAS_CHECK ((*it
).first
== i
, internal_logic ()); // broken map
375 return &(*it
).second
;
380 const_reference
operator () (size_type i
) const {
381 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
382 const_subiterator_type
it (data ().find (i
));
383 if (it
== data ().end ())
385 BOOST_UBLAS_CHECK ((*it
).first
== i
, internal_logic ()); // broken map
389 true_reference
ref (size_type i
) {
390 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
391 std::pair
<subiterator_type
, bool> ii (data ().insert (typename
array_type::value_type (i
, value_type
/*zero*/())));
392 BOOST_UBLAS_CHECK ((ii
.first
)->first
== i
, internal_logic ()); // broken map
393 return (ii
.first
)->second
;
396 reference
operator () (size_type i
) {
397 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
400 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
401 return reference (*this, i
);
406 const_reference
operator [] (size_type i
) const {
410 reference
operator [] (size_type i
) {
414 // Element assignment
416 true_reference
insert_element (size_type i
, const_reference t
) {
417 std::pair
<subiterator_type
, bool> ii
= data ().insert (typename
array_type::value_type (i
, t
));
418 BOOST_UBLAS_CHECK (ii
.second
, bad_index ()); // duplicate element
419 BOOST_UBLAS_CHECK ((ii
.first
)->first
== i
, internal_logic ()); // broken map
420 if (!ii
.second
) // existing element
421 (ii
.first
)->second
= t
;
422 return (ii
.first
)->second
;
425 void erase_element (size_type i
) {
426 subiterator_type it
= data ().find (i
);
427 if (it
== data ().end ())
440 mapped_vector
&operator = (const mapped_vector
&v
) {
447 template<class C
> // Container assignment without temporary
449 mapped_vector
&operator = (const vector_container
<C
> &v
) {
450 resize (v ().size (), false);
455 mapped_vector
&assign_temporary (mapped_vector
&v
) {
461 mapped_vector
&operator = (const vector_expression
<AE
> &ae
) {
462 self_type
temporary (ae
, detail::map_capacity (data()));
463 return assign_temporary (temporary
);
467 mapped_vector
&assign (const vector_expression
<AE
> &ae
) {
468 vector_assign
<scalar_assign
> (*this, ae
);
472 // Computed assignment
475 mapped_vector
&operator += (const vector_expression
<AE
> &ae
) {
476 self_type
temporary (*this + ae
, detail::map_capacity (data()));
477 return assign_temporary (temporary
);
479 template<class C
> // Container assignment without temporary
481 mapped_vector
&operator += (const vector_container
<C
> &v
) {
487 mapped_vector
&plus_assign (const vector_expression
<AE
> &ae
) {
488 vector_assign
<scalar_plus_assign
> (*this, ae
);
493 mapped_vector
&operator -= (const vector_expression
<AE
> &ae
) {
494 self_type
temporary (*this - ae
, detail::map_capacity (data()));
495 return assign_temporary (temporary
);
497 template<class C
> // Container assignment without temporary
499 mapped_vector
&operator -= (const vector_container
<C
> &v
) {
505 mapped_vector
&minus_assign (const vector_expression
<AE
> &ae
) {
506 vector_assign
<scalar_minus_assign
> (*this, ae
);
511 mapped_vector
&operator *= (const AT
&at
) {
512 vector_assign_scalar
<scalar_multiplies_assign
> (*this, at
);
517 mapped_vector
&operator /= (const AT
&at
) {
518 vector_assign_scalar
<scalar_divides_assign
> (*this, at
);
524 void swap (mapped_vector
&v
) {
526 std::swap (size_
, v
.size_
);
527 data ().swap (v
.data ());
531 friend void swap (mapped_vector
&v1
, mapped_vector
&v2
) {
537 // Use storage iterator
538 typedef typename
A::const_iterator const_subiterator_type
;
539 typedef typename
A::iterator subiterator_type
;
542 true_reference
at_element (size_type i
) {
543 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
544 subiterator_type
it (data ().find (i
));
545 BOOST_UBLAS_CHECK (it
!= data ().end(), bad_index ());
546 BOOST_UBLAS_CHECK ((*it
).first
== i
, internal_logic ()); // broken map
551 class const_iterator
;
555 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
556 const_iterator
find (size_type i
) const {
557 return const_iterator (*this, data ().lower_bound (i
));
559 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
560 iterator
find (size_type i
) {
561 return iterator (*this, data ().lower_bound (i
));
565 class const_iterator
:
566 public container_const_reference
<mapped_vector
>,
567 public bidirectional_iterator_base
<sparse_bidirectional_iterator_tag
,
568 const_iterator
, value_type
> {
570 typedef typename
mapped_vector::value_type value_type
;
571 typedef typename
mapped_vector::difference_type difference_type
;
572 typedef typename
mapped_vector::const_reference reference
;
573 typedef const typename
mapped_vector::pointer pointer
;
575 // Construction and destruction
578 container_const_reference
<self_type
> (), it_ () {}
580 const_iterator (const self_type
&v
, const const_subiterator_type
&it
):
581 container_const_reference
<self_type
> (v
), it_ (it
) {}
583 const_iterator (const typename
self_type::iterator
&it
): // ISSUE self_type:: stops VC8 using std::iterator here
584 container_const_reference
<self_type
> (it ()), it_ (it
.it_
) {}
588 const_iterator
&operator ++ () {
593 const_iterator
&operator -- () {
600 const_reference
operator * () const {
601 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
602 return (*it_
).second
;
607 size_type
index () const {
608 BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
609 BOOST_UBLAS_CHECK ((*it_
).first
< (*this) ().size (), bad_index ());
615 const_iterator
&operator = (const const_iterator
&it
) {
616 container_const_reference
<self_type
>::assign (&it ());
623 bool operator == (const const_iterator
&it
) const {
624 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
625 return it_
== it
.it_
;
629 const_subiterator_type it_
;
633 const_iterator
begin () const {
634 return const_iterator (*this, data ().begin ());
637 const_iterator
end () const {
638 return const_iterator (*this, data ().end ());
642 public container_reference
<mapped_vector
>,
643 public bidirectional_iterator_base
<sparse_bidirectional_iterator_tag
,
644 iterator
, value_type
> {
646 typedef typename
mapped_vector::value_type value_type
;
647 typedef typename
mapped_vector::difference_type difference_type
;
648 typedef typename
mapped_vector::true_reference reference
;
649 typedef typename
mapped_vector::pointer pointer
;
651 // Construction and destruction
654 container_reference
<self_type
> (), it_ () {}
656 iterator (self_type
&v
, const subiterator_type
&it
):
657 container_reference
<self_type
> (v
), it_ (it
) {}
661 iterator
&operator ++ () {
666 iterator
&operator -- () {
673 reference
operator * () const {
674 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
675 return (*it_
).second
;
680 size_type
index () const {
681 BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
682 BOOST_UBLAS_CHECK ((*it_
).first
< (*this) ().size (), bad_index ());
688 iterator
&operator = (const iterator
&it
) {
689 container_reference
<self_type
>::assign (&it ());
696 bool operator == (const iterator
&it
) const {
697 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
698 return it_
== it
.it_
;
702 subiterator_type it_
;
704 friend class const_iterator
;
709 return iterator (*this, data ().begin ());
713 return iterator (*this, data ().end ());
717 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
718 typedef reverse_iterator_base
<iterator
> reverse_iterator
;
721 const_reverse_iterator
rbegin () const {
722 return const_reverse_iterator (end ());
725 const_reverse_iterator
rend () const {
726 return const_reverse_iterator (begin ());
729 reverse_iterator
rbegin () {
730 return reverse_iterator (end ());
733 reverse_iterator
rend () {
734 return reverse_iterator (begin ());
738 template<class Archive
>
739 void serialize(Archive
& ar
, const unsigned int /* file_version */){
740 serialization::collection_size_type
s (size_
);
741 ar
& serialization::make_nvp("size",s
);
742 if (Archive::is_loading::value
) {
745 ar
& serialization::make_nvp("data", data_
);
751 static const value_type zero_
;
754 template<class T
, class A
>
755 const typename mapped_vector
<T
, A
>::value_type mapped_vector
<T
, A
>::zero_
= value_type
/*zero*/();
758 // Compressed array based sparse vector class
759 // Thanks to Kresimir Fresl for extending this to cover different index bases.
760 template<class T
, std::size_t IB
, class IA
, class TA
>
761 class compressed_vector
:
762 public vector_container
<compressed_vector
<T
, IB
, IA
, TA
> > {
764 typedef T
&true_reference
;
766 typedef const T
*const_pointer
;
767 typedef compressed_vector
<T
, IB
, IA
, TA
> self_type
;
769 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
770 using vector_container
<self_type
>::operator ();
772 // ISSUE require type consistency check
773 // is_convertable (IA::size_type, TA::size_type)
774 typedef typename
IA::value_type size_type
;
775 typedef typename
IA::difference_type difference_type
;
776 typedef T value_type
;
777 typedef const T
&const_reference
;
778 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
779 typedef T
&reference
;
781 typedef sparse_vector_element
<self_type
> reference
;
783 typedef IA index_array_type
;
784 typedef TA value_array_type
;
785 typedef const vector_reference
<const self_type
> const_closure_type
;
786 typedef vector_reference
<self_type
> closure_type
;
787 typedef self_type vector_temporary_type
;
788 typedef sparse_tag storage_category
;
790 // Construction and destruction
792 compressed_vector ():
793 vector_container
<self_type
> (),
794 size_ (0), capacity_ (restrict_capacity (0)), filled_ (0),
795 index_data_ (capacity_
), value_data_ (capacity_
) {
796 storage_invariants ();
798 explicit BOOST_UBLAS_INLINE
799 compressed_vector (size_type size
, size_type non_zeros
= 0):
800 vector_container
<self_type
> (),
801 size_ (size
), capacity_ (restrict_capacity (non_zeros
)), filled_ (0),
802 index_data_ (capacity_
), value_data_ (capacity_
) {
803 storage_invariants ();
806 compressed_vector (const compressed_vector
&v
):
807 vector_container
<self_type
> (),
808 size_ (v
.size_
), capacity_ (v
.capacity_
), filled_ (v
.filled_
),
809 index_data_ (v
.index_data_
), value_data_ (v
.value_data_
) {
810 storage_invariants ();
814 compressed_vector (const vector_expression
<AE
> &ae
, size_type non_zeros
= 0):
815 vector_container
<self_type
> (),
816 size_ (ae ().size ()), capacity_ (restrict_capacity (non_zeros
)), filled_ (0),
817 index_data_ (capacity_
), value_data_ (capacity_
) {
818 storage_invariants ();
819 vector_assign
<scalar_assign
> (*this, ae
);
824 size_type
size () const {
828 size_type
nnz_capacity () const {
832 size_type
nnz () const {
838 static size_type
index_base () {
842 typename
index_array_type::size_type
filled () const {
846 const index_array_type
&index_data () const {
850 const value_array_type
&value_data () const {
854 void set_filled (const typename
index_array_type::size_type
& filled
) {
856 storage_invariants ();
859 index_array_type
&index_data () {
863 value_array_type
&value_data () {
870 size_type
restrict_capacity (size_type non_zeros
) const {
871 non_zeros
= (std::max
) (non_zeros
, size_type (1));
872 non_zeros
= (std::min
) (non_zeros
, size_
);
877 void resize (size_type size
, bool preserve
= true) {
879 capacity_
= restrict_capacity (capacity_
);
881 index_data_
. resize (capacity_
, size_type ());
882 value_data_
. resize (capacity_
, value_type ());
883 filled_
= (std::min
) (capacity_
, filled_
);
884 while ((filled_
> 0) && (zero_based(index_data_
[filled_
- 1]) >= size
)) {
889 index_data_
. resize (capacity_
);
890 value_data_
. resize (capacity_
);
893 storage_invariants ();
898 void reserve (size_type non_zeros
, bool preserve
= true) {
899 capacity_
= restrict_capacity (non_zeros
);
901 index_data_
. resize (capacity_
, size_type ());
902 value_data_
. resize (capacity_
, value_type ());
903 filled_
= (std::min
) (capacity_
, filled_
);
906 index_data_
. resize (capacity_
);
907 value_data_
. resize (capacity_
);
910 storage_invariants ();
915 pointer
find_element (size_type i
) {
916 return const_cast<pointer
> (const_cast<const self_type
&>(*this).find_element (i
));
919 const_pointer
find_element (size_type i
) const {
920 const_subiterator_type
it (detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
921 if (it
== index_data_
.begin () + filled_
|| *it
!= k_based (i
))
923 return &value_data_
[it
- index_data_
.begin ()];
928 const_reference
operator () (size_type i
) const {
929 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
930 const_subiterator_type
it (detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
931 if (it
== index_data_
.begin () + filled_
|| *it
!= k_based (i
))
933 return value_data_
[it
- index_data_
.begin ()];
936 true_reference
ref (size_type i
) {
937 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
938 subiterator_type
it (detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
939 if (it
== index_data_
.begin () + filled_
|| *it
!= k_based (i
))
940 return insert_element (i
, value_type
/*zero*/());
942 return value_data_
[it
- index_data_
.begin ()];
945 reference
operator () (size_type i
) {
946 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
949 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
950 return reference (*this, i
);
955 const_reference
operator [] (size_type i
) const {
959 reference
operator [] (size_type i
) {
963 // Element assignment
965 true_reference
insert_element (size_type i
, const_reference t
) {
966 BOOST_UBLAS_CHECK (!find_element (i
), bad_index ()); // duplicate element
967 if (filled_
>= capacity_
)
968 reserve (2 * capacity_
, true);
969 subiterator_type
it (detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
970 // ISSUE max_capacity limit due to difference_type
971 typename
std::iterator_traits
<subiterator_type
>::difference_type n
= it
- index_data_
.begin ();
972 BOOST_UBLAS_CHECK (filled_
== 0 || filled_
== typename
index_array_type::size_type (n
) || *it
!= k_based (i
), internal_logic ()); // duplicate found by lower_bound
974 it
= index_data_
.begin () + n
;
975 std::copy_backward (it
, index_data_
.begin () + filled_
- 1, index_data_
.begin () + filled_
);
977 typename
value_array_type::iterator
itt (value_data_
.begin () + n
);
978 std::copy_backward (itt
, value_data_
.begin () + filled_
- 1, value_data_
.begin () + filled_
);
980 storage_invariants ();
984 void erase_element (size_type i
) {
985 subiterator_type
it (detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
986 typename
std::iterator_traits
<subiterator_type
>::difference_type n
= it
- index_data_
.begin ();
987 if (filled_
> typename
index_array_type::size_type (n
) && *it
== k_based (i
)) {
988 std::copy (it
+ 1, index_data_
.begin () + filled_
, it
);
989 typename
value_array_type::iterator
itt (value_data_
.begin () + n
);
990 std::copy (itt
+ 1, value_data_
.begin () + filled_
, itt
);
993 storage_invariants ();
1000 storage_invariants ();
1005 compressed_vector
&operator = (const compressed_vector
&v
) {
1008 capacity_
= v
.capacity_
;
1009 filled_
= v
.filled_
;
1010 index_data_
= v
.index_data_
;
1011 value_data_
= v
.value_data_
;
1013 storage_invariants ();
1016 template<class C
> // Container assignment without temporary
1018 compressed_vector
&operator = (const vector_container
<C
> &v
) {
1019 resize (v ().size (), false);
1024 compressed_vector
&assign_temporary (compressed_vector
&v
) {
1030 compressed_vector
&operator = (const vector_expression
<AE
> &ae
) {
1031 self_type
temporary (ae
, capacity_
);
1032 return assign_temporary (temporary
);
1036 compressed_vector
&assign (const vector_expression
<AE
> &ae
) {
1037 vector_assign
<scalar_assign
> (*this, ae
);
1041 // Computed assignment
1044 compressed_vector
&operator += (const vector_expression
<AE
> &ae
) {
1045 self_type
temporary (*this + ae
, capacity_
);
1046 return assign_temporary (temporary
);
1048 template<class C
> // Container assignment without temporary
1050 compressed_vector
&operator += (const vector_container
<C
> &v
) {
1056 compressed_vector
&plus_assign (const vector_expression
<AE
> &ae
) {
1057 vector_assign
<scalar_plus_assign
> (*this, ae
);
1062 compressed_vector
&operator -= (const vector_expression
<AE
> &ae
) {
1063 self_type
temporary (*this - ae
, capacity_
);
1064 return assign_temporary (temporary
);
1066 template<class C
> // Container assignment without temporary
1068 compressed_vector
&operator -= (const vector_container
<C
> &v
) {
1074 compressed_vector
&minus_assign (const vector_expression
<AE
> &ae
) {
1075 vector_assign
<scalar_minus_assign
> (*this, ae
);
1080 compressed_vector
&operator *= (const AT
&at
) {
1081 vector_assign_scalar
<scalar_multiplies_assign
> (*this, at
);
1086 compressed_vector
&operator /= (const AT
&at
) {
1087 vector_assign_scalar
<scalar_divides_assign
> (*this, at
);
1093 void swap (compressed_vector
&v
) {
1095 std::swap (size_
, v
.size_
);
1096 std::swap (capacity_
, v
.capacity_
);
1097 std::swap (filled_
, v
.filled_
);
1098 index_data_
.swap (v
.index_data_
);
1099 value_data_
.swap (v
.value_data_
);
1101 storage_invariants ();
1104 friend void swap (compressed_vector
&v1
, compressed_vector
&v2
) {
1108 // Back element insertion and erasure
1110 void push_back (size_type i
, const_reference t
) {
1111 BOOST_UBLAS_CHECK (filled_
== 0 || index_data_
[filled_
- 1] < k_based (i
), external_logic ());
1112 if (filled_
>= capacity_
)
1113 reserve (2 * capacity_
, true);
1114 BOOST_UBLAS_CHECK (filled_
< capacity_
, internal_logic ());
1115 index_data_
[filled_
] = k_based (i
);
1116 value_data_
[filled_
] = t
;
1118 storage_invariants ();
1122 BOOST_UBLAS_CHECK (filled_
> 0, external_logic ());
1124 storage_invariants ();
1129 // Use index array iterator
1130 typedef typename
IA::const_iterator const_subiterator_type
;
1131 typedef typename
IA::iterator subiterator_type
;
1134 true_reference
at_element (size_type i
) {
1135 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
1136 subiterator_type
it (detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
1137 BOOST_UBLAS_CHECK (it
!= index_data_
.begin () + filled_
&& *it
== k_based (i
), bad_index ());
1138 return value_data_
[it
- index_data_
.begin ()];
1142 class const_iterator
;
1146 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1147 const_iterator
find (size_type i
) const {
1148 return const_iterator (*this, detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
1150 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1151 iterator
find (size_type i
) {
1152 return iterator (*this, detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
1156 class const_iterator
:
1157 public container_const_reference
<compressed_vector
>,
1158 public bidirectional_iterator_base
<sparse_bidirectional_iterator_tag
,
1159 const_iterator
, value_type
> {
1161 typedef typename
compressed_vector::value_type value_type
;
1162 typedef typename
compressed_vector::difference_type difference_type
;
1163 typedef typename
compressed_vector::const_reference reference
;
1164 typedef const typename
compressed_vector::pointer pointer
;
1166 // Construction and destruction
1169 container_const_reference
<self_type
> (), it_ () {}
1171 const_iterator (const self_type
&v
, const const_subiterator_type
&it
):
1172 container_const_reference
<self_type
> (v
), it_ (it
) {}
1174 const_iterator (const typename
self_type::iterator
&it
): // ISSUE self_type:: stops VC8 using std::iterator here
1175 container_const_reference
<self_type
> (it ()), it_ (it
.it_
) {}
1179 const_iterator
&operator ++ () {
1184 const_iterator
&operator -- () {
1191 const_reference
operator * () const {
1192 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1193 return (*this) ().value_data_
[it_
- (*this) ().index_data_
.begin ()];
1198 size_type
index () const {
1199 BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
1200 BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_
) < (*this) ().size (), bad_index ());
1201 return (*this) ().zero_based (*it_
);
1206 const_iterator
&operator = (const const_iterator
&it
) {
1207 container_const_reference
<self_type
>::assign (&it ());
1214 bool operator == (const const_iterator
&it
) const {
1215 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1216 return it_
== it
.it_
;
1220 const_subiterator_type it_
;
1224 const_iterator
begin () const {
1228 const_iterator
end () const {
1229 return find (size_
);
1233 public container_reference
<compressed_vector
>,
1234 public bidirectional_iterator_base
<sparse_bidirectional_iterator_tag
,
1235 iterator
, value_type
> {
1237 typedef typename
compressed_vector::value_type value_type
;
1238 typedef typename
compressed_vector::difference_type difference_type
;
1239 typedef typename
compressed_vector::true_reference reference
;
1240 typedef typename
compressed_vector::pointer pointer
;
1242 // Construction and destruction
1245 container_reference
<self_type
> (), it_ () {}
1247 iterator (self_type
&v
, const subiterator_type
&it
):
1248 container_reference
<self_type
> (v
), it_ (it
) {}
1252 iterator
&operator ++ () {
1257 iterator
&operator -- () {
1264 reference
operator * () const {
1265 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1266 return (*this) ().value_data_
[it_
- (*this) ().index_data_
.begin ()];
1271 size_type
index () const {
1272 BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
1273 BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_
) < (*this) ().size (), bad_index ());
1274 return (*this) ().zero_based (*it_
);
1279 iterator
&operator = (const iterator
&it
) {
1280 container_reference
<self_type
>::assign (&it ());
1287 bool operator == (const iterator
&it
) const {
1288 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1289 return it_
== it
.it_
;
1293 subiterator_type it_
;
1295 friend class const_iterator
;
1304 return find (size_
);
1308 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
1309 typedef reverse_iterator_base
<iterator
> reverse_iterator
;
1312 const_reverse_iterator
rbegin () const {
1313 return const_reverse_iterator (end ());
1316 const_reverse_iterator
rend () const {
1317 return const_reverse_iterator (begin ());
1320 reverse_iterator
rbegin () {
1321 return reverse_iterator (end ());
1324 reverse_iterator
rend () {
1325 return reverse_iterator (begin ());
1329 template<class Archive
>
1330 void serialize(Archive
& ar
, const unsigned int /* file_version */){
1331 serialization::collection_size_type
s (size_
);
1332 ar
& serialization::make_nvp("size",s
);
1333 if (Archive::is_loading::value
) {
1336 // ISSUE: filled may be much less than capacity
1337 // ISSUE: index_data_ and value_data_ are undefined between filled and capacity (trouble with 'nan'-values)
1338 ar
& serialization::make_nvp("capacity", capacity_
);
1339 ar
& serialization::make_nvp("filled", filled_
);
1340 ar
& serialization::make_nvp("index_data", index_data_
);
1341 ar
& serialization::make_nvp("value_data", value_data_
);
1342 storage_invariants();
1346 void storage_invariants () const
1348 BOOST_UBLAS_CHECK (capacity_
== index_data_
.size (), internal_logic ());
1349 BOOST_UBLAS_CHECK (capacity_
== value_data_
.size (), internal_logic ());
1350 BOOST_UBLAS_CHECK (filled_
<= capacity_
, internal_logic ());
1351 BOOST_UBLAS_CHECK ((0 == filled_
) || (zero_based(index_data_
[filled_
- 1]) < size_
), internal_logic ());
1355 typename
index_array_type::size_type capacity_
;
1356 typename
index_array_type::size_type filled_
;
1357 index_array_type index_data_
;
1358 value_array_type value_data_
;
1359 static const value_type zero_
;
1362 static size_type
zero_based (size_type k_based_index
) {
1363 return k_based_index
- IB
;
1366 static size_type
k_based (size_type zero_based_index
) {
1367 return zero_based_index
+ IB
;
1370 friend class iterator
;
1371 friend class const_iterator
;
1374 template<class T
, std::size_t IB
, class IA
, class TA
>
1375 const typename compressed_vector
<T
, IB
, IA
, TA
>::value_type compressed_vector
<T
, IB
, IA
, TA
>::zero_
= value_type
/*zero*/();
1378 // Coordimate array based sparse vector class
1379 // Thanks to Kresimir Fresl for extending this to cover different index bases.
1380 template<class T
, std::size_t IB
, class IA
, class TA
>
1381 class coordinate_vector
:
1382 public vector_container
<coordinate_vector
<T
, IB
, IA
, TA
> > {
1384 typedef T
&true_reference
;
1386 typedef const T
*const_pointer
;
1387 typedef coordinate_vector
<T
, IB
, IA
, TA
> self_type
;
1389 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1390 using vector_container
<self_type
>::operator ();
1392 // ISSUE require type consistency check
1393 // is_convertable (IA::size_type, TA::size_type)
1394 typedef typename
IA::value_type size_type
;
1395 typedef typename
IA::difference_type difference_type
;
1396 typedef T value_type
;
1397 typedef const T
&const_reference
;
1398 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
1399 typedef T
&reference
;
1401 typedef sparse_vector_element
<self_type
> reference
;
1403 typedef IA index_array_type
;
1404 typedef TA value_array_type
;
1405 typedef const vector_reference
<const self_type
> const_closure_type
;
1406 typedef vector_reference
<self_type
> closure_type
;
1407 typedef self_type vector_temporary_type
;
1408 typedef sparse_tag storage_category
;
1410 // Construction and destruction
1412 coordinate_vector ():
1413 vector_container
<self_type
> (),
1414 size_ (0), capacity_ (restrict_capacity (0)),
1415 filled_ (0), sorted_filled_ (filled_
), sorted_ (true),
1416 index_data_ (capacity_
), value_data_ (capacity_
) {
1417 storage_invariants ();
1419 explicit BOOST_UBLAS_INLINE
1420 coordinate_vector (size_type size
, size_type non_zeros
= 0):
1421 vector_container
<self_type
> (),
1422 size_ (size
), capacity_ (restrict_capacity (non_zeros
)),
1423 filled_ (0), sorted_filled_ (filled_
), sorted_ (true),
1424 index_data_ (capacity_
), value_data_ (capacity_
) {
1425 storage_invariants ();
1428 coordinate_vector (const coordinate_vector
&v
):
1429 vector_container
<self_type
> (),
1430 size_ (v
.size_
), capacity_ (v
.capacity_
),
1431 filled_ (v
.filled_
), sorted_filled_ (v
.sorted_filled_
), sorted_ (v
.sorted_
),
1432 index_data_ (v
.index_data_
), value_data_ (v
.value_data_
) {
1433 storage_invariants ();
1437 coordinate_vector (const vector_expression
<AE
> &ae
, size_type non_zeros
= 0):
1438 vector_container
<self_type
> (),
1439 size_ (ae ().size ()), capacity_ (restrict_capacity (non_zeros
)),
1440 filled_ (0), sorted_filled_ (filled_
), sorted_ (true),
1441 index_data_ (capacity_
), value_data_ (capacity_
) {
1442 storage_invariants ();
1443 vector_assign
<scalar_assign
> (*this, ae
);
1448 size_type
size () const {
1452 size_type
nnz_capacity () const {
1456 size_type
nnz () const {
1460 // Storage accessors
1462 static size_type
index_base () {
1466 typename
index_array_type::size_type
filled () const {
1470 const index_array_type
&index_data () const {
1474 const value_array_type
&value_data () const {
1478 void set_filled (const typename
index_array_type::size_type
&sorted
, const typename
index_array_type::size_type
&filled
) {
1479 sorted_filled_
= sorted
;
1481 storage_invariants ();
1485 index_array_type
&index_data () {
1489 value_array_type
&value_data () {
1496 size_type
restrict_capacity (size_type non_zeros
) const {
1497 // minimum non_zeros
1498 non_zeros
= (std::max
) (non_zeros
, size_type (1));
1499 // ISSUE no maximum as coordinate may contain inserted duplicates
1504 void resize (size_type size
, bool preserve
= true) {
1506 sort (); // remove duplicate elements.
1508 capacity_
= restrict_capacity (capacity_
);
1510 index_data_
. resize (capacity_
, size_type ());
1511 value_data_
. resize (capacity_
, value_type ());
1512 filled_
= (std::min
) (capacity_
, filled_
);
1513 while ((filled_
> 0) && (zero_based(index_data_
[filled_
- 1]) >= size
)) {
1518 index_data_
. resize (capacity_
);
1519 value_data_
. resize (capacity_
);
1522 sorted_filled_
= filled_
;
1523 storage_invariants ();
1527 void reserve (size_type non_zeros
, bool preserve
= true) {
1529 sort (); // remove duplicate elements.
1530 capacity_
= restrict_capacity (non_zeros
);
1532 index_data_
. resize (capacity_
, size_type ());
1533 value_data_
. resize (capacity_
, value_type ());
1534 filled_
= (std::min
) (capacity_
, filled_
);
1537 index_data_
. resize (capacity_
);
1538 value_data_
. resize (capacity_
);
1541 sorted_filled_
= filled_
;
1542 storage_invariants ();
1547 pointer
find_element (size_type i
) {
1548 return const_cast<pointer
> (const_cast<const self_type
&>(*this).find_element (i
));
1551 const_pointer
find_element (size_type i
) const {
1553 const_subiterator_type
it (detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
1554 if (it
== index_data_
.begin () + filled_
|| *it
!= k_based (i
))
1556 return &value_data_
[it
- index_data_
.begin ()];
1561 const_reference
operator () (size_type i
) const {
1562 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
1564 const_subiterator_type
it (detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
1565 if (it
== index_data_
.begin () + filled_
|| *it
!= k_based (i
))
1567 return value_data_
[it
- index_data_
.begin ()];
1570 true_reference
ref (size_type i
) {
1571 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
1573 subiterator_type
it (detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
1574 if (it
== index_data_
.begin () + filled_
|| *it
!= k_based (i
))
1575 return insert_element (i
, value_type
/*zero*/());
1577 return value_data_
[it
- index_data_
.begin ()];
1580 reference
operator () (size_type i
) {
1581 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
1584 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
1585 return reference (*this, i
);
1590 const_reference
operator [] (size_type i
) const {
1594 reference
operator [] (size_type i
) {
1598 // Element assignment
1600 void append_element (size_type i
, const_reference t
) {
1601 if (filled_
>= capacity_
)
1602 reserve (2 * filled_
, true);
1603 BOOST_UBLAS_CHECK (filled_
< capacity_
, internal_logic ());
1604 index_data_
[filled_
] = k_based (i
);
1605 value_data_
[filled_
] = t
;
1608 storage_invariants ();
1611 true_reference
insert_element (size_type i
, const_reference t
) {
1612 BOOST_UBLAS_CHECK (!find_element (i
), bad_index ()); // duplicate element
1613 append_element (i
, t
);
1614 return value_data_
[filled_
- 1];
1617 void erase_element (size_type i
) {
1619 subiterator_type
it (detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
1620 typename
std::iterator_traits
<subiterator_type
>::difference_type n
= it
- index_data_
.begin ();
1621 if (filled_
> typename
index_array_type::size_type (n
) && *it
== k_based (i
)) {
1622 std::copy (it
+ 1, index_data_
.begin () + filled_
, it
);
1623 typename
value_array_type::iterator
itt (value_data_
.begin () + n
);
1624 std::copy (itt
+ 1, value_data_
.begin () + filled_
, itt
);
1626 sorted_filled_
= filled_
;
1628 storage_invariants ();
1635 sorted_filled_
= filled_
;
1637 storage_invariants ();
1642 coordinate_vector
&operator = (const coordinate_vector
&v
) {
1645 capacity_
= v
.capacity_
;
1646 filled_
= v
.filled_
;
1647 sorted_filled_
= v
.sorted_filled_
;
1648 sorted_
= v
.sorted_
;
1649 index_data_
= v
.index_data_
;
1650 value_data_
= v
.value_data_
;
1652 storage_invariants ();
1655 template<class C
> // Container assignment without temporary
1657 coordinate_vector
&operator = (const vector_container
<C
> &v
) {
1658 resize (v ().size (), false);
1663 coordinate_vector
&assign_temporary (coordinate_vector
&v
) {
1669 coordinate_vector
&operator = (const vector_expression
<AE
> &ae
) {
1670 self_type
temporary (ae
, capacity_
);
1671 return assign_temporary (temporary
);
1675 coordinate_vector
&assign (const vector_expression
<AE
> &ae
) {
1676 vector_assign
<scalar_assign
> (*this, ae
);
1680 // Computed assignment
1683 coordinate_vector
&operator += (const vector_expression
<AE
> &ae
) {
1684 self_type
temporary (*this + ae
, capacity_
);
1685 return assign_temporary (temporary
);
1687 template<class C
> // Container assignment without temporary
1689 coordinate_vector
&operator += (const vector_container
<C
> &v
) {
1695 coordinate_vector
&plus_assign (const vector_expression
<AE
> &ae
) {
1696 vector_assign
<scalar_plus_assign
> (*this, ae
);
1701 coordinate_vector
&operator -= (const vector_expression
<AE
> &ae
) {
1702 self_type
temporary (*this - ae
, capacity_
);
1703 return assign_temporary (temporary
);
1705 template<class C
> // Container assignment without temporary
1707 coordinate_vector
&operator -= (const vector_container
<C
> &v
) {
1713 coordinate_vector
&minus_assign (const vector_expression
<AE
> &ae
) {
1714 vector_assign
<scalar_minus_assign
> (*this, ae
);
1719 coordinate_vector
&operator *= (const AT
&at
) {
1720 vector_assign_scalar
<scalar_multiplies_assign
> (*this, at
);
1725 coordinate_vector
&operator /= (const AT
&at
) {
1726 vector_assign_scalar
<scalar_divides_assign
> (*this, at
);
1732 void swap (coordinate_vector
&v
) {
1734 std::swap (size_
, v
.size_
);
1735 std::swap (capacity_
, v
.capacity_
);
1736 std::swap (filled_
, v
.filled_
);
1737 std::swap (sorted_filled_
, v
.sorted_filled_
);
1738 std::swap (sorted_
, v
.sorted_
);
1739 index_data_
.swap (v
.index_data_
);
1740 value_data_
.swap (v
.value_data_
);
1742 storage_invariants ();
1745 friend void swap (coordinate_vector
&v1
, coordinate_vector
&v2
) {
1749 // Sorting and summation of duplicates
1751 void sort () const {
1752 if (! sorted_
&& filled_
> 0) {
1753 typedef index_pair_array
<index_array_type
, value_array_type
> array_pair
;
1754 array_pair
ipa (filled_
, index_data_
, value_data_
);
1755 const typename
array_pair::iterator iunsorted
= ipa
.begin () + sorted_filled_
;
1756 // sort new elements and merge
1757 std::sort (iunsorted
, ipa
.end ());
1758 std::inplace_merge (ipa
.begin (), iunsorted
, ipa
.end ());
1760 // sum duplicates with += and remove
1761 size_type filled
= 0;
1762 for (size_type i
= 1; i
< filled_
; ++ i
) {
1763 if (index_data_
[filled
] != index_data_
[i
]) {
1766 index_data_
[filled
] = index_data_
[i
];
1767 value_data_
[filled
] = value_data_
[i
];
1770 value_data_
[filled
] += value_data_
[i
];
1773 filled_
= filled
+ 1;
1774 sorted_filled_
= filled_
;
1776 storage_invariants ();
1780 // Back element insertion and erasure
1782 void push_back (size_type i
, const_reference t
) {
1783 // must maintain sort order
1784 BOOST_UBLAS_CHECK (sorted_
&& (filled_
== 0 || index_data_
[filled_
- 1] < k_based (i
)), external_logic ());
1785 if (filled_
>= capacity_
)
1786 reserve (2 * filled_
, true);
1787 BOOST_UBLAS_CHECK (filled_
< capacity_
, internal_logic ());
1788 index_data_
[filled_
] = k_based (i
);
1789 value_data_
[filled_
] = t
;
1791 sorted_filled_
= filled_
;
1792 storage_invariants ();
1796 // ISSUE invariants could be simpilfied if sorted required as precondition
1797 BOOST_UBLAS_CHECK (filled_
> 0, external_logic ());
1799 sorted_filled_
= (std::min
) (sorted_filled_
, filled_
);
1800 sorted_
= sorted_filled_
= filled_
;
1801 storage_invariants ();
1806 // Use index array iterator
1807 typedef typename
IA::const_iterator const_subiterator_type
;
1808 typedef typename
IA::iterator subiterator_type
;
1811 true_reference
at_element (size_type i
) {
1812 BOOST_UBLAS_CHECK (i
< size_
, bad_index ());
1814 subiterator_type
it (detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
1815 BOOST_UBLAS_CHECK (it
!= index_data_
.begin () + filled_
&& *it
== k_based (i
), bad_index ());
1816 return value_data_
[it
- index_data_
.begin ()];
1820 class const_iterator
;
1824 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1825 const_iterator
find (size_type i
) const {
1827 return const_iterator (*this, detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
1829 // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1830 iterator
find (size_type i
) {
1832 return iterator (*this, detail::lower_bound (index_data_
.begin (), index_data_
.begin () + filled_
, k_based (i
), std::less
<size_type
> ()));
1836 class const_iterator
:
1837 public container_const_reference
<coordinate_vector
>,
1838 public bidirectional_iterator_base
<sparse_bidirectional_iterator_tag
,
1839 const_iterator
, value_type
> {
1841 typedef typename
coordinate_vector::value_type value_type
;
1842 typedef typename
coordinate_vector::difference_type difference_type
;
1843 typedef typename
coordinate_vector::const_reference reference
;
1844 typedef const typename
coordinate_vector::pointer pointer
;
1846 // Construction and destruction
1849 container_const_reference
<self_type
> (), it_ () {}
1851 const_iterator (const self_type
&v
, const const_subiterator_type
&it
):
1852 container_const_reference
<self_type
> (v
), it_ (it
) {}
1854 const_iterator (const typename
self_type::iterator
&it
): // ISSUE self_type:: stops VC8 using std::iterator here
1855 container_const_reference
<self_type
> (it ()), it_ (it
.it_
) {}
1859 const_iterator
&operator ++ () {
1864 const_iterator
&operator -- () {
1871 const_reference
operator * () const {
1872 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1873 return (*this) ().value_data_
[it_
- (*this) ().index_data_
.begin ()];
1878 size_type
index () const {
1879 BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
1880 BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_
) < (*this) ().size (), bad_index ());
1881 return (*this) ().zero_based (*it_
);
1886 const_iterator
&operator = (const const_iterator
&it
) {
1887 container_const_reference
<self_type
>::assign (&it ());
1894 bool operator == (const const_iterator
&it
) const {
1895 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1896 return it_
== it
.it_
;
1900 const_subiterator_type it_
;
1904 const_iterator
begin () const {
1908 const_iterator
end () const {
1909 return find (size_
);
1913 public container_reference
<coordinate_vector
>,
1914 public bidirectional_iterator_base
<sparse_bidirectional_iterator_tag
,
1915 iterator
, value_type
> {
1917 typedef typename
coordinate_vector::value_type value_type
;
1918 typedef typename
coordinate_vector::difference_type difference_type
;
1919 typedef typename
coordinate_vector::true_reference reference
;
1920 typedef typename
coordinate_vector::pointer pointer
;
1922 // Construction and destruction
1925 container_reference
<self_type
> (), it_ () {}
1927 iterator (self_type
&v
, const subiterator_type
&it
):
1928 container_reference
<self_type
> (v
), it_ (it
) {}
1932 iterator
&operator ++ () {
1937 iterator
&operator -- () {
1944 reference
operator * () const {
1945 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1946 return (*this) ().value_data_
[it_
- (*this) ().index_data_
.begin ()];
1951 size_type
index () const {
1952 BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
1953 BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_
) < (*this) ().size (), bad_index ());
1954 return (*this) ().zero_based (*it_
);
1959 iterator
&operator = (const iterator
&it
) {
1960 container_reference
<self_type
>::assign (&it ());
1967 bool operator == (const iterator
&it
) const {
1968 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1969 return it_
== it
.it_
;
1973 subiterator_type it_
;
1975 friend class const_iterator
;
1984 return find (size_
);
1988 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
1989 typedef reverse_iterator_base
<iterator
> reverse_iterator
;
1992 const_reverse_iterator
rbegin () const {
1993 return const_reverse_iterator (end ());
1996 const_reverse_iterator
rend () const {
1997 return const_reverse_iterator (begin ());
2000 reverse_iterator
rbegin () {
2001 return reverse_iterator (end ());
2004 reverse_iterator
rend () {
2005 return reverse_iterator (begin ());
2009 template<class Archive
>
2010 void serialize(Archive
& ar
, const unsigned int /* file_version */){
2011 serialization::collection_size_type
s (size_
);
2012 ar
& serialization::make_nvp("size",s
);
2013 if (Archive::is_loading::value
) {
2016 // ISSUE: filled may be much less than capacity
2017 // ISSUE: index_data_ and value_data_ are undefined between filled and capacity (trouble with 'nan'-values)
2018 ar
& serialization::make_nvp("capacity", capacity_
);
2019 ar
& serialization::make_nvp("filled", filled_
);
2020 ar
& serialization::make_nvp("sorted_filled", sorted_filled_
);
2021 ar
& serialization::make_nvp("sorted", sorted_
);
2022 ar
& serialization::make_nvp("index_data", index_data_
);
2023 ar
& serialization::make_nvp("value_data", value_data_
);
2024 storage_invariants();
2028 void storage_invariants () const
2030 BOOST_UBLAS_CHECK (capacity_
== index_data_
.size (), internal_logic ());
2031 BOOST_UBLAS_CHECK (capacity_
== value_data_
.size (), internal_logic ());
2032 BOOST_UBLAS_CHECK (filled_
<= capacity_
, internal_logic ());
2033 BOOST_UBLAS_CHECK (sorted_filled_
<= filled_
, internal_logic ());
2034 BOOST_UBLAS_CHECK (sorted_
== (sorted_filled_
== filled_
), internal_logic ());
2035 BOOST_UBLAS_CHECK ((0 == filled_
) || (zero_based(index_data_
[filled_
- 1]) < size_
), internal_logic ());
2039 size_type capacity_
;
2040 mutable typename
index_array_type::size_type filled_
;
2041 mutable typename
index_array_type::size_type sorted_filled_
;
2042 mutable bool sorted_
;
2043 mutable index_array_type index_data_
;
2044 mutable value_array_type value_data_
;
2045 static const value_type zero_
;
2048 static size_type
zero_based (size_type k_based_index
) {
2049 return k_based_index
- IB
;
2052 static size_type
k_based (size_type zero_based_index
) {
2053 return zero_based_index
+ IB
;
2056 friend class iterator
;
2057 friend class const_iterator
;
2060 template<class T
, std::size_t IB
, class IA
, class TA
>
2061 const typename coordinate_vector
<T
, IB
, IA
, TA
>::value_type coordinate_vector
<T
, IB
, IA
, TA
>::zero_
= value_type
/*zero*/();