New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
vector_sparse.hpp in vendors/XIOS/current/extern/boost/include/boost/numeric/ublas – NEMO

source: vendors/XIOS/current/extern/boost/include/boost/numeric/ublas/vector_sparse.hpp @ 3428

Last change on this file since 3428 was 3428, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

File size: 77.9 KB
Line 
1//
2//  Copyright (c) 2000-2002
3//  Joerg Walter, Mathias Koch
4//
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)
8//
9//  The authors gratefully acknowledge the support of
10//  GeNeSys mbH & Co. KG in producing this work.
11//
12
13#ifndef _BOOST_UBLAS_VECTOR_SPARSE_
14#define _BOOST_UBLAS_VECTOR_SPARSE_
15
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>
21#endif
22
23// Iterators based on ideas of Jeremy Siek
24
25namespace boost { namespace numeric { namespace ublas {
26
27#ifdef BOOST_UBLAS_STRICT_VECTOR_SPARSE
28
29    template<class V>
30    class sparse_vector_element:
31       public container_reference<V> {
32    public:
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;
38
39    private:
40        // Proxied element operations
41        void get_d () const {
42            pointer p = (*this) ().find_element (i_);
43            if (p)
44                d_ = *p;
45            else
46                d_ = value_type/*zero*/();
47        }
48
49        void set (const value_type &s) const {
50            pointer p = (*this) ().find_element (i_);
51            if (!p)
52                (*this) ().insert_element (i_, s);
53            else
54                *p = s;
55        }
56
57    public:
58        // Construction and destruction
59        sparse_vector_element (vector_type &v, size_type i):
60            container_reference<vector_type> (v), i_ (i) {
61        }
62        BOOST_UBLAS_INLINE
63        sparse_vector_element (const sparse_vector_element &p):
64            container_reference<vector_type> (p), i_ (p.i_) {}
65        BOOST_UBLAS_INLINE
66        ~sparse_vector_element () {
67        }
68
69        // Assignment
70        BOOST_UBLAS_INLINE
71        sparse_vector_element &operator = (const sparse_vector_element &p) {
72            // Overide the implict copy assignment
73            p.get_d ();
74            set (p.d_);
75            return *this;
76        }
77        template<class D>
78        BOOST_UBLAS_INLINE
79        sparse_vector_element &operator = (const D &d) {
80            set (d);
81            return *this;
82        }
83        template<class D>
84        BOOST_UBLAS_INLINE
85        sparse_vector_element &operator += (const D &d) {
86            get_d ();
87            d_ += d;
88            set (d_);
89            return *this;
90        }
91        template<class D>
92        BOOST_UBLAS_INLINE
93        sparse_vector_element &operator -= (const D &d) {
94            get_d ();
95            d_ -= d;
96            set (d_);
97            return *this;
98        }
99        template<class D>
100        BOOST_UBLAS_INLINE
101        sparse_vector_element &operator *= (const D &d) {
102            get_d ();
103            d_ *= d;
104            set (d_);
105            return *this;
106        }
107        template<class D>
108        BOOST_UBLAS_INLINE
109        sparse_vector_element &operator /= (const D &d) {
110            get_d ();
111            d_ /= d;
112            set (d_);
113            return *this;
114        }
115
116        // Comparison
117        template<class D>
118        BOOST_UBLAS_INLINE
119        bool operator == (const D &d) const {
120            get_d ();
121            return d_ == d;
122        }
123        template<class D>
124        BOOST_UBLAS_INLINE
125        bool operator != (const D &d) const {
126            get_d ();
127            return d_ != d;
128        }
129
130        // Conversion - weak link in proxy as d_ is not a perfect alias for the element
131        BOOST_UBLAS_INLINE
132        operator const_reference () const {
133            get_d ();
134            return d_;
135        }
136
137        // Conversion to reference - may be invalidated
138        BOOST_UBLAS_INLINE
139        value_type& ref () const {
140            const pointer p = (*this) ().find_element (i_);
141            if (!p)
142                return (*this) ().insert_element (i_, value_type/*zero*/());
143            else
144                return *p;
145        }
146
147    private:
148        size_type i_;
149        mutable value_type d_;
150    };
151
152    /*
153     * Generalise explicit reference access
154     */
155    namespace detail {
156        template <class R>
157        struct element_reference {
158            typedef R& reference;
159            static reference get_reference (reference r)
160            {
161                return r;
162            }
163        };
164        template <class V>
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)
168            {
169                return sve.ref ();
170            }
171        };
172    }
173    template <class VER>
174    typename detail::element_reference<VER>::reference ref (VER& ver) {
175        return detail::element_reference<VER>::get_reference (ver);
176    }
177    template <class VER>
178    typename detail::element_reference<VER>::reference ref (const VER& ver) {
179        return detail::element_reference<VER>::get_reference (ver);
180    }
181
182
183    template<class V>
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;
192
193        static const unsigned plus_complexity = type_traits<element_type>::plus_complexity;
194        static const unsigned multiplies_complexity = type_traits<element_type>::multiplies_complexity;
195
196        static
197        BOOST_UBLAS_INLINE
198        real_type real (const_reference t) {
199            return type_traits<element_type>::real (t);
200        }
201        static
202        BOOST_UBLAS_INLINE
203        real_type imag (const_reference t) {
204            return type_traits<element_type>::imag (t);
205        }
206        static
207        BOOST_UBLAS_INLINE
208        value_type conj (const_reference t) {
209            return type_traits<element_type>::conj (t);
210        }
211
212        static
213        BOOST_UBLAS_INLINE
214        real_type type_abs (const_reference t) {
215            return type_traits<element_type>::type_abs (t);
216        }
217        static
218        BOOST_UBLAS_INLINE
219        value_type type_sqrt (const_reference t) {
220            return type_traits<element_type>::type_sqrt (t);
221        }
222
223        static
224        BOOST_UBLAS_INLINE
225        real_type norm_1 (const_reference t) {
226            return type_traits<element_type>::norm_1 (t);
227        }
228        static
229        BOOST_UBLAS_INLINE
230        real_type norm_2 (const_reference t) {
231            return type_traits<element_type>::norm_2 (t);
232        }
233        static
234        BOOST_UBLAS_INLINE
235        real_type norm_inf (const_reference t) {
236            return type_traits<element_type>::norm_inf (t);
237        }
238
239        static
240        BOOST_UBLAS_INLINE
241        bool equals (const_reference t1, const_reference t2) {
242            return type_traits<element_type>::equals (t1, t2);
243        }
244    };
245
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;
249    };
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;
253    };
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;
258    };
259
260#endif
261
262
263    /** \brief Index map based sparse vector
264     *
265     * A sparse vector of values of type T of variable size. The sparse storage type A can be
266     * \c std::map<size_t, T> or \c map_array<size_t, T>. This means that only non-zero elements
267     * are effectively stored.
268     *
269     * For a \f$n\f$-dimensional sparse vector,  and 0 <= i < n the non-zero elements \f$v_i\f$
270     * are mapped to consecutive elements of the associative container, i.e. for elements
271     * \f$k = v_{i_1}\f$ and \f$k + 1 = v_{i_2}\f$ of the container, holds \f$i_1 < i_2\f$.
272     *
273     * Supported parameters for the adapted array are \c map_array<std::size_t, T> and
274     * \c map_std<std::size_t, T>. The latter is equivalent to \c std::map<std::size_t, T>.
275     *
276     * \tparam T the type of object stored in the vector (like double, float, complex, etc...)
277     * \tparam A the type of Storage array
278     */
279    template<class T, class A>
280    class mapped_vector:
281        public vector_container<mapped_vector<T, A> > {
282
283        typedef T &true_reference;
284        typedef T *pointer;
285        typedef const T *const_pointer;
286        typedef mapped_vector<T, A> self_type;
287    public:
288#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
289        using vector_container<self_type>::operator ();
290#endif
291        typedef typename A::size_type size_type;
292        typedef typename A::difference_type difference_type;
293        typedef T value_type;
294        typedef A array_type;
295        typedef const value_type &const_reference;
296#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
297        typedef typename detail::map_traits<A,T>::reference reference;
298#else
299        typedef sparse_vector_element<self_type> reference;
300#endif
301        typedef const vector_reference<const self_type> const_closure_type;
302        typedef vector_reference<self_type> closure_type;
303        typedef self_type vector_temporary_type;
304        typedef sparse_tag storage_category;
305
306        // Construction and destruction
307        BOOST_UBLAS_INLINE
308        mapped_vector ():
309            vector_container<self_type> (),
310            size_ (0), data_ () {}
311        BOOST_UBLAS_INLINE
312        mapped_vector (size_type size, size_type non_zeros = 0):
313            vector_container<self_type> (),
314            size_ (size), data_ () {
315            detail::map_reserve (data(), restrict_capacity (non_zeros));
316        }
317        BOOST_UBLAS_INLINE
318        mapped_vector (const mapped_vector &v):
319            vector_container<self_type> (),
320            size_ (v.size_), data_ (v.data_) {}
321        template<class AE>
322        BOOST_UBLAS_INLINE
323        mapped_vector (const vector_expression<AE> &ae, size_type non_zeros = 0):
324            vector_container<self_type> (),
325            size_ (ae ().size ()), data_ () {
326            detail::map_reserve (data(), restrict_capacity (non_zeros));
327            vector_assign<scalar_assign> (*this, ae);
328        }
329
330        // Accessors
331        BOOST_UBLAS_INLINE
332        size_type size () const {
333            return size_;
334        }
335        BOOST_UBLAS_INLINE
336        size_type nnz_capacity () const {
337            return detail::map_capacity (data ());
338        }
339        BOOST_UBLAS_INLINE
340        size_type nnz () const {
341            return data (). size ();
342        }
343
344        // Storage accessors
345        BOOST_UBLAS_INLINE
346        const array_type &data () const {
347            return data_;
348        }
349        BOOST_UBLAS_INLINE
350        array_type &data () {
351            return data_;
352        }
353
354        // Resizing
355    private:
356        BOOST_UBLAS_INLINE
357        size_type restrict_capacity (size_type non_zeros) const {
358            non_zeros = (std::min) (non_zeros, size_);
359            return non_zeros;
360        }
361    public:
362        BOOST_UBLAS_INLINE
363        void resize (size_type size, bool preserve = true) {
364            size_ = size;
365            if (preserve) {
366                data ().erase (data ().lower_bound(size_), data ().end());
367            }
368            else {
369                data ().clear ();
370            }
371        }
372
373        // Reserving
374        BOOST_UBLAS_INLINE
375        void reserve (size_type non_zeros = 0, bool preserve = true) {
376            detail::map_reserve (data (), restrict_capacity (non_zeros));
377        }
378
379        // Element support
380        BOOST_UBLAS_INLINE
381        pointer find_element (size_type i) {
382            return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
383        }
384        BOOST_UBLAS_INLINE
385        const_pointer find_element (size_type i) const {
386            const_subiterator_type it (data ().find (i));
387            if (it == data ().end ())
388                return 0;
389            BOOST_UBLAS_CHECK ((*it).first == i, internal_logic ());   // broken map
390            return &(*it).second;
391        }
392
393        // Element access
394        BOOST_UBLAS_INLINE
395        const_reference operator () (size_type i) const {
396            BOOST_UBLAS_CHECK (i < size_, bad_index ());
397            const_subiterator_type it (data ().find (i));
398            if (it == data ().end ())
399                return zero_;
400            BOOST_UBLAS_CHECK ((*it).first == i, internal_logic ());   // broken map
401            return (*it).second;
402        }
403        BOOST_UBLAS_INLINE
404        true_reference ref (size_type i) {
405            BOOST_UBLAS_CHECK (i < size_, bad_index ());
406            std::pair<subiterator_type, bool> ii (data ().insert (typename array_type::value_type (i, value_type/*zero*/())));
407            BOOST_UBLAS_CHECK ((ii.first)->first == i, internal_logic ());   // broken map
408            return (ii.first)->second;
409        }
410        BOOST_UBLAS_INLINE
411        reference operator () (size_type i) {
412#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
413            return ref (i);
414#else
415            BOOST_UBLAS_CHECK (i < size_, bad_index ());
416            return reference (*this, i);
417#endif
418        }
419
420        BOOST_UBLAS_INLINE
421        const_reference operator [] (size_type i) const {
422            return (*this) (i);
423        }
424        BOOST_UBLAS_INLINE
425        reference operator [] (size_type i) {
426            return (*this) (i);
427        }
428
429        // Element assignment
430        BOOST_UBLAS_INLINE
431        true_reference insert_element (size_type i, const_reference t) {
432            std::pair<subiterator_type, bool> ii = data ().insert (typename array_type::value_type (i, t));
433            BOOST_UBLAS_CHECK (ii.second, bad_index ());        // duplicate element
434            BOOST_UBLAS_CHECK ((ii.first)->first == i, internal_logic ());   // broken map
435            if (!ii.second)     // existing element
436                (ii.first)->second = t;
437            return (ii.first)->second;
438        }
439        BOOST_UBLAS_INLINE
440        void erase_element (size_type i) {
441            subiterator_type it = data ().find (i);
442            if (it == data ().end ())
443                return;
444            data ().erase (it);
445        }
446
447        // Zeroing
448        BOOST_UBLAS_INLINE
449        void clear () {
450            data ().clear ();
451        }
452
453        // Assignment
454        BOOST_UBLAS_INLINE
455        mapped_vector &operator = (const mapped_vector &v) {
456            if (this != &v) {
457                size_ = v.size_;
458                data () = v.data ();
459            }
460            return *this;
461        }
462        template<class C>          // Container assignment without temporary
463        BOOST_UBLAS_INLINE
464        mapped_vector &operator = (const vector_container<C> &v) {
465            resize (v ().size (), false);
466            assign (v);
467            return *this;
468        }
469        BOOST_UBLAS_INLINE
470        mapped_vector &assign_temporary (mapped_vector &v) {
471            swap (v);
472            return *this;
473        }
474        template<class AE>
475        BOOST_UBLAS_INLINE
476        mapped_vector &operator = (const vector_expression<AE> &ae) {
477            self_type temporary (ae, detail::map_capacity (data()));
478            return assign_temporary (temporary);
479        }
480        template<class AE>
481        BOOST_UBLAS_INLINE
482        mapped_vector &assign (const vector_expression<AE> &ae) {
483            vector_assign<scalar_assign> (*this, ae);
484            return *this;
485        }
486
487        // Computed assignment
488        template<class AE>
489        BOOST_UBLAS_INLINE
490        mapped_vector &operator += (const vector_expression<AE> &ae) {
491            self_type temporary (*this + ae, detail::map_capacity (data()));
492            return assign_temporary (temporary);
493        }
494        template<class C>          // Container assignment without temporary
495        BOOST_UBLAS_INLINE
496        mapped_vector &operator += (const vector_container<C> &v) {
497            plus_assign (v);
498            return *this;
499        }
500        template<class AE>
501        BOOST_UBLAS_INLINE
502        mapped_vector &plus_assign (const vector_expression<AE> &ae) {
503            vector_assign<scalar_plus_assign> (*this, ae);
504            return *this;
505        }
506        template<class AE>
507        BOOST_UBLAS_INLINE
508        mapped_vector &operator -= (const vector_expression<AE> &ae) {
509            self_type temporary (*this - ae, detail::map_capacity (data()));
510            return assign_temporary (temporary);
511        }
512        template<class C>          // Container assignment without temporary
513        BOOST_UBLAS_INLINE
514        mapped_vector &operator -= (const vector_container<C> &v) {
515            minus_assign (v);
516            return *this;
517        }
518        template<class AE>
519        BOOST_UBLAS_INLINE
520        mapped_vector &minus_assign (const vector_expression<AE> &ae) {
521            vector_assign<scalar_minus_assign> (*this, ae);
522            return *this;
523        }
524        template<class AT>
525        BOOST_UBLAS_INLINE
526        mapped_vector &operator *= (const AT &at) {
527            vector_assign_scalar<scalar_multiplies_assign> (*this, at);
528            return *this;
529        }
530        template<class AT>
531        BOOST_UBLAS_INLINE
532        mapped_vector &operator /= (const AT &at) {
533            vector_assign_scalar<scalar_divides_assign> (*this, at);
534            return *this;
535        }
536
537        // Swapping
538        BOOST_UBLAS_INLINE
539        void swap (mapped_vector &v) {
540            if (this != &v) {
541                std::swap (size_, v.size_);
542                data ().swap (v.data ());
543            }
544        }
545        BOOST_UBLAS_INLINE
546        friend void swap (mapped_vector &v1, mapped_vector &v2) {
547            v1.swap (v2);
548        }
549
550        // Iterator types
551    private:
552        // Use storage iterator
553        typedef typename A::const_iterator const_subiterator_type;
554        typedef typename A::iterator subiterator_type;
555
556        BOOST_UBLAS_INLINE
557        true_reference at_element (size_type i) {
558            BOOST_UBLAS_CHECK (i < size_, bad_index ());
559            subiterator_type it (data ().find (i));
560            BOOST_UBLAS_CHECK (it != data ().end(), bad_index ());
561            BOOST_UBLAS_CHECK ((*it).first == i, internal_logic ());   // broken map
562            return it->second;
563        }
564
565    public:
566        class const_iterator;
567        class iterator;
568
569        // Element lookup
570        // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
571        const_iterator find (size_type i) const {
572            return const_iterator (*this, data ().lower_bound (i));
573        }
574        // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
575        iterator find (size_type i) {
576            return iterator (*this, data ().lower_bound (i));
577        }
578
579
580        class const_iterator:
581            public container_const_reference<mapped_vector>,
582            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
583                                               const_iterator, value_type> {
584        public:
585            typedef typename mapped_vector::value_type value_type;
586            typedef typename mapped_vector::difference_type difference_type;
587            typedef typename mapped_vector::const_reference reference;
588            typedef const typename mapped_vector::pointer pointer;
589
590            // Construction and destruction
591            BOOST_UBLAS_INLINE
592            const_iterator ():
593                container_const_reference<self_type> (), it_ () {}
594            BOOST_UBLAS_INLINE
595            const_iterator (const self_type &v, const const_subiterator_type &it):
596                container_const_reference<self_type> (v), it_ (it) {}
597            BOOST_UBLAS_INLINE
598            const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
599                container_const_reference<self_type> (it ()), it_ (it.it_) {}
600
601            // Arithmetic
602            BOOST_UBLAS_INLINE
603            const_iterator &operator ++ () {
604                ++ it_;
605                return *this;
606            }
607            BOOST_UBLAS_INLINE
608            const_iterator &operator -- () {
609                -- it_;
610                return *this;
611            }
612
613            // Dereference
614            BOOST_UBLAS_INLINE
615            const_reference operator * () const {
616                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
617                return (*it_).second;
618            }
619
620            // Index
621            BOOST_UBLAS_INLINE
622            size_type index () const {
623                BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
624                BOOST_UBLAS_CHECK ((*it_).first < (*this) ().size (), bad_index ());
625                return (*it_).first;
626            }
627
628            // Assignment
629            BOOST_UBLAS_INLINE
630            const_iterator &operator = (const const_iterator &it) {
631                container_const_reference<self_type>::assign (&it ());
632                it_ = it.it_;
633                return *this;
634            }
635
636            // Comparison
637            BOOST_UBLAS_INLINE
638            bool operator == (const const_iterator &it) const {
639                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
640                return it_ == it.it_;
641            }
642
643        private:
644            const_subiterator_type it_;
645        };
646
647        BOOST_UBLAS_INLINE
648        const_iterator begin () const {
649            return const_iterator (*this, data ().begin ());
650        }
651        BOOST_UBLAS_INLINE
652        const_iterator end () const {
653            return const_iterator (*this, data ().end ());
654        }
655
656        class iterator:
657            public container_reference<mapped_vector>,
658            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
659                                               iterator, value_type> {
660        public:
661            typedef typename mapped_vector::value_type value_type;
662            typedef typename mapped_vector::difference_type difference_type;
663            typedef typename mapped_vector::true_reference reference;
664            typedef typename mapped_vector::pointer pointer;
665
666            // Construction and destruction
667            BOOST_UBLAS_INLINE
668            iterator ():
669                container_reference<self_type> (), it_ () {}
670            BOOST_UBLAS_INLINE
671            iterator (self_type &v, const subiterator_type &it):
672                container_reference<self_type> (v), it_ (it) {}
673
674            // Arithmetic
675            BOOST_UBLAS_INLINE
676            iterator &operator ++ () {
677                ++ it_;
678                return *this;
679            }
680            BOOST_UBLAS_INLINE
681            iterator &operator -- () {
682                -- it_;
683                return *this;
684            }
685
686            // Dereference
687            BOOST_UBLAS_INLINE
688            reference operator * () const {
689                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
690                return (*it_).second;
691            }
692
693            // Index
694            BOOST_UBLAS_INLINE
695            size_type index () const {
696                BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
697                BOOST_UBLAS_CHECK ((*it_).first < (*this) ().size (), bad_index ());
698                return (*it_).first;
699            }
700
701            // Assignment
702            BOOST_UBLAS_INLINE
703            iterator &operator = (const iterator &it) {
704                container_reference<self_type>::assign (&it ());
705                it_ = it.it_;
706                return *this;
707            }
708
709            // Comparison
710            BOOST_UBLAS_INLINE
711            bool operator == (const iterator &it) const {
712                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
713                return it_ == it.it_;
714            }
715
716        private:
717            subiterator_type it_;
718
719            friend class const_iterator;
720        };
721
722        BOOST_UBLAS_INLINE
723        iterator begin () {
724            return iterator (*this, data ().begin ());
725        }
726        BOOST_UBLAS_INLINE
727        iterator end () {
728            return iterator (*this, data ().end ());
729        }
730
731        // Reverse iterator
732        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
733        typedef reverse_iterator_base<iterator> reverse_iterator;
734
735        BOOST_UBLAS_INLINE
736        const_reverse_iterator rbegin () const {
737            return const_reverse_iterator (end ());
738        }
739        BOOST_UBLAS_INLINE
740        const_reverse_iterator rend () const {
741            return const_reverse_iterator (begin ());
742        }
743        BOOST_UBLAS_INLINE
744        reverse_iterator rbegin () {
745            return reverse_iterator (end ());
746        }
747        BOOST_UBLAS_INLINE
748        reverse_iterator rend () {
749            return reverse_iterator (begin ());
750        }
751
752         // Serialization
753        template<class Archive>
754        void serialize(Archive & ar, const unsigned int /* file_version */){
755            serialization::collection_size_type s (size_);
756            ar & serialization::make_nvp("size",s);
757            if (Archive::is_loading::value) {
758                size_ = s;
759            }
760            ar & serialization::make_nvp("data", data_);
761        }
762
763    private:
764        size_type size_;
765        array_type data_;
766        static const value_type zero_;
767    };
768
769    template<class T, class A>
770    const typename mapped_vector<T, A>::value_type mapped_vector<T, A>::zero_ = value_type/*zero*/();
771
772
773    // Thanks to Kresimir Fresl for extending this to cover different index bases.
774   
775    /** \brief Compressed array based sparse vector
776     *
777     * a sparse vector of values of type T of variable size. The non zero values are stored as
778     * two seperate arrays: an index array and a value array. The index array is always sorted
779     * and there is at most one entry for each index. Inserting an element can be time consuming.
780     * If the vector contains a few zero entries, then it is better to have a normal vector.
781     * If the vector has a very high dimension with a few non-zero values, then this vector is
782     * very memory efficient (at the cost of a few more computations).
783     *
784     * For a \f$n\f$-dimensional compressed vector and \f$0 \leq i < n\f$ the non-zero elements
785     * \f$v_i\f$ are mapped to consecutive elements of the index and value container, i.e. for
786     * elements \f$k = v_{i_1}\f$ and \f$k + 1 = v_{i_2}\f$ of these containers holds \f$i_1 < i_2\f$.
787     *
788     * Supported parameters for the adapted array (indices and values) are \c unbounded_array<> ,
789     * \c bounded_array<> and \c std::vector<>.
790     *
791     * \tparam T the type of object stored in the vector (like double, float, complex, etc...)
792     * \tparam IB the index base of the compressed vector. Default is 0. Other supported value is 1
793     * \tparam IA the type of adapted array for indices. Default is \c unbounded_array<std::size_t>
794     * \tparam TA the type of adapted array for values. Default is unbounded_array<T>
795     */
796    template<class T, std::size_t IB, class IA, class TA>
797    class compressed_vector:
798        public vector_container<compressed_vector<T, IB, IA, TA> > {
799
800        typedef T &true_reference;
801        typedef T *pointer;
802        typedef const T *const_pointer;
803        typedef compressed_vector<T, IB, IA, TA> self_type;
804    public:
805#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
806        using vector_container<self_type>::operator ();
807#endif
808        // ISSUE require type consistency check
809        // is_convertable (IA::size_type, TA::size_type)
810        typedef typename IA::value_type size_type;
811        typedef typename IA::difference_type difference_type;
812        typedef T value_type;
813        typedef const T &const_reference;
814#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
815        typedef T &reference;
816#else
817        typedef sparse_vector_element<self_type> reference;
818#endif
819        typedef IA index_array_type;
820        typedef TA value_array_type;
821        typedef const vector_reference<const self_type> const_closure_type;
822        typedef vector_reference<self_type> closure_type;
823        typedef self_type vector_temporary_type;
824        typedef sparse_tag storage_category;
825
826        // Construction and destruction
827        BOOST_UBLAS_INLINE
828        compressed_vector ():
829            vector_container<self_type> (),
830            size_ (0), capacity_ (restrict_capacity (0)), filled_ (0),
831            index_data_ (capacity_), value_data_ (capacity_) {
832            storage_invariants ();
833        }
834        explicit BOOST_UBLAS_INLINE
835        compressed_vector (size_type size, size_type non_zeros = 0):
836            vector_container<self_type> (),
837            size_ (size), capacity_ (restrict_capacity (non_zeros)), filled_ (0),
838            index_data_ (capacity_), value_data_ (capacity_) {
839        storage_invariants ();
840        }
841        BOOST_UBLAS_INLINE
842        compressed_vector (const compressed_vector &v):
843            vector_container<self_type> (),
844            size_ (v.size_), capacity_ (v.capacity_), filled_ (v.filled_),
845            index_data_ (v.index_data_), value_data_ (v.value_data_) {
846            storage_invariants ();
847        }
848        template<class AE>
849        BOOST_UBLAS_INLINE
850        compressed_vector (const vector_expression<AE> &ae, size_type non_zeros = 0):
851            vector_container<self_type> (),
852            size_ (ae ().size ()), capacity_ (restrict_capacity (non_zeros)), filled_ (0),
853            index_data_ (capacity_), value_data_ (capacity_) {
854            storage_invariants ();
855            vector_assign<scalar_assign> (*this, ae);
856        }
857
858        // Accessors
859        BOOST_UBLAS_INLINE
860        size_type size () const {
861            return size_;
862        }
863        BOOST_UBLAS_INLINE
864        size_type nnz_capacity () const {
865            return capacity_;
866        }
867        BOOST_UBLAS_INLINE
868        size_type nnz () const {
869            return filled_;
870        }
871
872        // Storage accessors
873        BOOST_UBLAS_INLINE
874        static size_type index_base () {
875            return IB;
876        }
877        BOOST_UBLAS_INLINE
878        typename index_array_type::size_type filled () const {
879            return filled_;
880        }
881        BOOST_UBLAS_INLINE
882        const index_array_type &index_data () const {
883            return index_data_;
884        }
885        BOOST_UBLAS_INLINE
886        const value_array_type &value_data () const {
887            return value_data_;
888        }
889        BOOST_UBLAS_INLINE
890        void set_filled (const typename index_array_type::size_type & filled) {
891            filled_ = filled;
892            storage_invariants ();
893        }
894        BOOST_UBLAS_INLINE
895        index_array_type &index_data () {
896            return index_data_;
897        }
898        BOOST_UBLAS_INLINE
899        value_array_type &value_data () {
900            return value_data_;
901        }
902
903        // Resizing
904    private:
905        BOOST_UBLAS_INLINE
906        size_type restrict_capacity (size_type non_zeros) const {
907            non_zeros = (std::max) (non_zeros, size_type (1));
908            non_zeros = (std::min) (non_zeros, size_);
909            return non_zeros;
910        }
911    public:
912        BOOST_UBLAS_INLINE
913        void resize (size_type size, bool preserve = true) {
914            size_ = size;
915            capacity_ = restrict_capacity (capacity_);
916            if (preserve) {
917                index_data_. resize (capacity_, size_type ());
918                value_data_. resize (capacity_, value_type ());
919                filled_ = (std::min) (capacity_, filled_);
920                while ((filled_ > 0) && (zero_based(index_data_[filled_ - 1]) >= size)) {
921                    --filled_;
922                }
923            }
924            else {
925                index_data_. resize (capacity_);
926                value_data_. resize (capacity_);
927                filled_ = 0;
928            }
929            storage_invariants ();
930        }
931
932        // Reserving
933        BOOST_UBLAS_INLINE
934        void reserve (size_type non_zeros, bool preserve = true) {
935            capacity_ = restrict_capacity (non_zeros);
936            if (preserve) {
937                index_data_. resize (capacity_, size_type ());
938                value_data_. resize (capacity_, value_type ());
939                filled_ = (std::min) (capacity_, filled_);
940            }
941            else {
942                index_data_. resize (capacity_);
943                value_data_. resize (capacity_);
944                filled_ = 0;
945            }
946            storage_invariants ();
947        }
948
949        // Element support
950        BOOST_UBLAS_INLINE
951        pointer find_element (size_type i) {
952            return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
953        }
954        BOOST_UBLAS_INLINE
955        const_pointer find_element (size_type i) const {
956            const_subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
957            if (it == index_data_.begin () + filled_ || *it != k_based (i))
958                return 0;
959            return &value_data_ [it - index_data_.begin ()];
960        }
961
962        // Element access
963        BOOST_UBLAS_INLINE
964        const_reference operator () (size_type i) const {
965            BOOST_UBLAS_CHECK (i < size_, bad_index ());
966            const_subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
967            if (it == index_data_.begin () + filled_ || *it != k_based (i))
968                return zero_;
969            return value_data_ [it - index_data_.begin ()];
970        }
971        BOOST_UBLAS_INLINE
972        true_reference ref (size_type i) {
973            BOOST_UBLAS_CHECK (i < size_, bad_index ());
974            subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
975            if (it == index_data_.begin () + filled_ || *it != k_based (i))
976                return insert_element (i, value_type/*zero*/());
977            else
978                return value_data_ [it - index_data_.begin ()];
979        }
980        BOOST_UBLAS_INLINE
981        reference operator () (size_type i) {
982#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
983            return ref (i) ;
984#else
985            BOOST_UBLAS_CHECK (i < size_, bad_index ());
986            return reference (*this, i);
987#endif
988        }
989
990        BOOST_UBLAS_INLINE
991        const_reference operator [] (size_type i) const {
992            return (*this) (i);
993        }
994        BOOST_UBLAS_INLINE
995        reference operator [] (size_type i) {
996            return (*this) (i);
997        }
998
999        // Element assignment
1000        BOOST_UBLAS_INLINE
1001        true_reference insert_element (size_type i, const_reference t) {
1002            BOOST_UBLAS_CHECK (!find_element (i), bad_index ());        // duplicate element
1003            if (filled_ >= capacity_)
1004                reserve (2 * capacity_, true);
1005            subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
1006            // ISSUE max_capacity limit due to difference_type
1007            typename std::iterator_traits<subiterator_type>::difference_type n = it - index_data_.begin ();
1008            BOOST_UBLAS_CHECK (filled_ == 0 || filled_ == typename index_array_type::size_type (n) || *it != k_based (i), internal_logic ());   // duplicate found by lower_bound
1009            ++ filled_;
1010            it = index_data_.begin () + n;
1011            std::copy_backward (it, index_data_.begin () + filled_ - 1, index_data_.begin () + filled_);
1012            *it = k_based (i);
1013            typename value_array_type::iterator itt (value_data_.begin () + n);
1014            std::copy_backward (itt, value_data_.begin () + filled_ - 1, value_data_.begin () + filled_);
1015            *itt = t;
1016            storage_invariants ();
1017            return *itt;
1018        }
1019        BOOST_UBLAS_INLINE
1020        void erase_element (size_type i) {
1021            subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
1022            typename std::iterator_traits<subiterator_type>::difference_type  n = it - index_data_.begin ();
1023            if (filled_ > typename index_array_type::size_type (n) && *it == k_based (i)) {
1024                std::copy (it + 1, index_data_.begin () + filled_, it);
1025                typename value_array_type::iterator itt (value_data_.begin () + n);
1026                std::copy (itt + 1, value_data_.begin () + filled_, itt);
1027                -- filled_;
1028            }
1029            storage_invariants ();
1030        }
1031
1032        // Zeroing
1033        BOOST_UBLAS_INLINE
1034        void clear () {
1035            filled_ = 0;
1036            storage_invariants ();
1037        }
1038
1039        // Assignment
1040        BOOST_UBLAS_INLINE
1041        compressed_vector &operator = (const compressed_vector &v) {
1042            if (this != &v) {
1043                size_ = v.size_;
1044                capacity_ = v.capacity_;
1045                filled_ = v.filled_;
1046                index_data_ = v.index_data_;
1047                value_data_ = v.value_data_;
1048            }
1049            storage_invariants ();
1050            return *this;
1051        }
1052        template<class C>          // Container assignment without temporary
1053        BOOST_UBLAS_INLINE
1054        compressed_vector &operator = (const vector_container<C> &v) {
1055            resize (v ().size (), false);
1056            assign (v);
1057            return *this;
1058        }
1059        BOOST_UBLAS_INLINE
1060        compressed_vector &assign_temporary (compressed_vector &v) {
1061            swap (v);
1062            return *this;
1063        }
1064        template<class AE>
1065        BOOST_UBLAS_INLINE
1066        compressed_vector &operator = (const vector_expression<AE> &ae) {
1067            self_type temporary (ae, capacity_);
1068            return assign_temporary (temporary);
1069        }
1070        template<class AE>
1071        BOOST_UBLAS_INLINE
1072        compressed_vector &assign (const vector_expression<AE> &ae) {
1073            vector_assign<scalar_assign> (*this, ae);
1074            return *this;
1075        }
1076
1077        // Computed assignment
1078        template<class AE>
1079        BOOST_UBLAS_INLINE
1080        compressed_vector &operator += (const vector_expression<AE> &ae) {
1081            self_type temporary (*this + ae, capacity_);
1082            return assign_temporary (temporary);
1083        }
1084        template<class C>          // Container assignment without temporary
1085        BOOST_UBLAS_INLINE
1086        compressed_vector &operator += (const vector_container<C> &v) {
1087            plus_assign (v);
1088            return *this;
1089        }
1090        template<class AE>
1091        BOOST_UBLAS_INLINE
1092        compressed_vector &plus_assign (const vector_expression<AE> &ae) {
1093            vector_assign<scalar_plus_assign> (*this, ae);
1094            return *this;
1095        }
1096        template<class AE>
1097        BOOST_UBLAS_INLINE
1098        compressed_vector &operator -= (const vector_expression<AE> &ae) {
1099            self_type temporary (*this - ae, capacity_);
1100            return assign_temporary (temporary);
1101        }
1102        template<class C>          // Container assignment without temporary
1103        BOOST_UBLAS_INLINE
1104        compressed_vector &operator -= (const vector_container<C> &v) {
1105            minus_assign (v);
1106            return *this;
1107        }
1108        template<class AE>
1109        BOOST_UBLAS_INLINE
1110        compressed_vector &minus_assign (const vector_expression<AE> &ae) {
1111            vector_assign<scalar_minus_assign> (*this, ae);
1112            return *this;
1113        }
1114        template<class AT>
1115        BOOST_UBLAS_INLINE
1116        compressed_vector &operator *= (const AT &at) {
1117            vector_assign_scalar<scalar_multiplies_assign> (*this, at);
1118            return *this;
1119        }
1120        template<class AT>
1121        BOOST_UBLAS_INLINE
1122        compressed_vector &operator /= (const AT &at) {
1123            vector_assign_scalar<scalar_divides_assign> (*this, at);
1124            return *this;
1125        }
1126
1127        // Swapping
1128        BOOST_UBLAS_INLINE
1129        void swap (compressed_vector &v) {
1130            if (this != &v) {
1131                std::swap (size_, v.size_);
1132                std::swap (capacity_, v.capacity_);
1133                std::swap (filled_, v.filled_);
1134                index_data_.swap (v.index_data_);
1135                value_data_.swap (v.value_data_);
1136            }
1137            storage_invariants ();
1138        }
1139        BOOST_UBLAS_INLINE
1140        friend void swap (compressed_vector &v1, compressed_vector &v2) {
1141            v1.swap (v2);
1142        }
1143
1144        // Back element insertion and erasure
1145        BOOST_UBLAS_INLINE
1146        void push_back (size_type i, const_reference t) {
1147            BOOST_UBLAS_CHECK (filled_ == 0 || index_data_ [filled_ - 1] < k_based (i), external_logic ());
1148            if (filled_ >= capacity_)
1149                reserve (2 * capacity_, true);
1150            BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
1151            index_data_ [filled_] = k_based (i);
1152            value_data_ [filled_] = t;
1153            ++ filled_;
1154            storage_invariants ();
1155        }
1156        BOOST_UBLAS_INLINE
1157        void pop_back () {
1158            BOOST_UBLAS_CHECK (filled_ > 0, external_logic ());
1159            -- filled_;
1160            storage_invariants ();
1161        }
1162
1163        // Iterator types
1164    private:
1165        // Use index array iterator
1166        typedef typename IA::const_iterator const_subiterator_type;
1167        typedef typename IA::iterator subiterator_type;
1168
1169        BOOST_UBLAS_INLINE
1170        true_reference at_element (size_type i) {
1171            BOOST_UBLAS_CHECK (i < size_, bad_index ());
1172            subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
1173            BOOST_UBLAS_CHECK (it != index_data_.begin () + filled_ && *it == k_based (i), bad_index ());
1174            return value_data_ [it - index_data_.begin ()];
1175        }
1176
1177    public:
1178        class const_iterator;
1179        class iterator;
1180
1181        // Element lookup
1182        // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1183        const_iterator find (size_type i) const {
1184            return const_iterator (*this, detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
1185        }
1186        // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1187        iterator find (size_type i) {
1188            return iterator (*this, detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
1189        }
1190
1191
1192        class const_iterator:
1193            public container_const_reference<compressed_vector>,
1194            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
1195                                               const_iterator, value_type> {
1196        public:
1197            typedef typename compressed_vector::value_type value_type;
1198            typedef typename compressed_vector::difference_type difference_type;
1199            typedef typename compressed_vector::const_reference reference;
1200            typedef const typename compressed_vector::pointer pointer;
1201
1202            // Construction and destruction
1203            BOOST_UBLAS_INLINE
1204            const_iterator ():
1205                container_const_reference<self_type> (), it_ () {}
1206            BOOST_UBLAS_INLINE
1207            const_iterator (const self_type &v, const const_subiterator_type &it):
1208                container_const_reference<self_type> (v), it_ (it) {}
1209            BOOST_UBLAS_INLINE
1210            const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
1211                container_const_reference<self_type> (it ()), it_ (it.it_) {}
1212
1213            // Arithmetic
1214            BOOST_UBLAS_INLINE
1215            const_iterator &operator ++ () {
1216                ++ it_;
1217                return *this;
1218            }
1219            BOOST_UBLAS_INLINE
1220            const_iterator &operator -- () {
1221                -- it_;
1222                return *this;
1223            }
1224
1225            // Dereference
1226            BOOST_UBLAS_INLINE
1227            const_reference operator * () const {
1228                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1229                return (*this) ().value_data_ [it_ - (*this) ().index_data_.begin ()];
1230            }
1231
1232            // Index
1233            BOOST_UBLAS_INLINE
1234            size_type index () const {
1235                BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
1236                BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
1237                return (*this) ().zero_based (*it_);
1238            }
1239
1240            // Assignment
1241            BOOST_UBLAS_INLINE
1242            const_iterator &operator = (const const_iterator &it) {
1243                container_const_reference<self_type>::assign (&it ());
1244                it_ = it.it_;
1245                return *this;
1246            }
1247
1248            // Comparison
1249            BOOST_UBLAS_INLINE
1250            bool operator == (const const_iterator &it) const {
1251                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1252                return it_ == it.it_;
1253            }
1254
1255        private:
1256            const_subiterator_type it_;
1257        };
1258
1259        BOOST_UBLAS_INLINE
1260        const_iterator begin () const {
1261            return find (0);
1262        }
1263        BOOST_UBLAS_INLINE
1264        const_iterator end () const {
1265            return find (size_);
1266        }
1267
1268        class iterator:
1269            public container_reference<compressed_vector>,
1270            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
1271                                               iterator, value_type> {
1272        public:
1273            typedef typename compressed_vector::value_type value_type;
1274            typedef typename compressed_vector::difference_type difference_type;
1275            typedef typename compressed_vector::true_reference reference;
1276            typedef typename compressed_vector::pointer pointer;
1277
1278            // Construction and destruction
1279            BOOST_UBLAS_INLINE
1280            iterator ():
1281                container_reference<self_type> (), it_ () {}
1282            BOOST_UBLAS_INLINE
1283            iterator (self_type &v, const subiterator_type &it):
1284                container_reference<self_type> (v), it_ (it) {}
1285
1286            // Arithmetic
1287            BOOST_UBLAS_INLINE
1288            iterator &operator ++ () {
1289                ++ it_;
1290                return *this;
1291            }
1292            BOOST_UBLAS_INLINE
1293            iterator &operator -- () {
1294                -- it_;
1295                return *this;
1296            }
1297
1298            // Dereference
1299            BOOST_UBLAS_INLINE
1300            reference operator * () const {
1301                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1302                return (*this) ().value_data_ [it_ - (*this) ().index_data_.begin ()];
1303            }
1304
1305            // Index
1306            BOOST_UBLAS_INLINE
1307            size_type index () const {
1308                BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
1309                BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
1310                return (*this) ().zero_based (*it_);
1311            }
1312
1313            // Assignment
1314            BOOST_UBLAS_INLINE
1315            iterator &operator = (const iterator &it) {
1316                container_reference<self_type>::assign (&it ());
1317                it_ = it.it_;
1318                return *this;
1319            }
1320
1321            // Comparison
1322            BOOST_UBLAS_INLINE
1323            bool operator == (const iterator &it) const {
1324                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1325                return it_ == it.it_;
1326            }
1327
1328        private:
1329            subiterator_type it_;
1330
1331            friend class const_iterator;
1332        };
1333
1334        BOOST_UBLAS_INLINE
1335        iterator begin () {
1336            return find (0);
1337        }
1338        BOOST_UBLAS_INLINE
1339        iterator end () {
1340            return find (size_);
1341        }
1342
1343        // Reverse iterator
1344        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1345        typedef reverse_iterator_base<iterator> reverse_iterator;
1346
1347        BOOST_UBLAS_INLINE
1348        const_reverse_iterator rbegin () const {
1349            return const_reverse_iterator (end ());
1350        }
1351        BOOST_UBLAS_INLINE
1352        const_reverse_iterator rend () const {
1353            return const_reverse_iterator (begin ());
1354        }
1355        BOOST_UBLAS_INLINE
1356        reverse_iterator rbegin () {
1357            return reverse_iterator (end ());
1358        }
1359        BOOST_UBLAS_INLINE
1360        reverse_iterator rend () {
1361            return reverse_iterator (begin ());
1362        }
1363
1364         // Serialization
1365        template<class Archive>
1366        void serialize(Archive & ar, const unsigned int /* file_version */){
1367            serialization::collection_size_type s (size_);
1368            ar & serialization::make_nvp("size",s);
1369            if (Archive::is_loading::value) {
1370                size_ = s;
1371            }
1372            // ISSUE: filled may be much less than capacity
1373            // ISSUE: index_data_ and value_data_ are undefined between filled and capacity (trouble with 'nan'-values)
1374            ar & serialization::make_nvp("capacity", capacity_);
1375            ar & serialization::make_nvp("filled", filled_);
1376            ar & serialization::make_nvp("index_data", index_data_);
1377            ar & serialization::make_nvp("value_data", value_data_);
1378            storage_invariants();
1379        }
1380
1381    private:
1382        void storage_invariants () const
1383        {
1384            BOOST_UBLAS_CHECK (capacity_ == index_data_.size (), internal_logic ());
1385            BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
1386            BOOST_UBLAS_CHECK (filled_ <= capacity_, internal_logic ());
1387            BOOST_UBLAS_CHECK ((0 == filled_) || (zero_based(index_data_[filled_ - 1]) < size_), internal_logic ());
1388        }
1389
1390        size_type size_;
1391        typename index_array_type::size_type capacity_;
1392        typename index_array_type::size_type filled_;
1393        index_array_type index_data_;
1394        value_array_type value_data_;
1395        static const value_type zero_;
1396
1397        BOOST_UBLAS_INLINE
1398        static size_type zero_based (size_type k_based_index) {
1399            return k_based_index - IB;
1400        }
1401        BOOST_UBLAS_INLINE
1402        static size_type k_based (size_type zero_based_index) {
1403            return zero_based_index + IB;
1404        }
1405
1406        friend class iterator;
1407        friend class const_iterator;
1408    };
1409
1410    template<class T, std::size_t IB, class IA, class TA>
1411    const typename compressed_vector<T, IB, IA, TA>::value_type compressed_vector<T, IB, IA, TA>::zero_ = value_type/*zero*/();
1412
1413    // Thanks to Kresimir Fresl for extending this to cover different index bases.
1414
1415    /** \brief Coordimate array based sparse vector
1416     *
1417     * a sparse vector of values of type \c T of variable size. The non zero values are stored
1418     * as two seperate arrays: an index array and a value array. The arrays may be out of order
1419     * with multiple entries for each vector element. If there are multiple values for the same
1420     * index the sum of these values is the real value. It is way more efficient for inserting values
1421     * than a \c compressed_vector but less memory efficient. Also linearly parsing a vector can
1422     * be longer in specific cases than a \c compressed_vector.
1423     *
1424     * For a n-dimensional sorted coordinate vector and \f$ 0 \leq i < n\f$ the non-zero elements
1425     * \f$v_i\f$ are mapped to consecutive elements of the index and value container, i.e. for
1426     * elements \f$k = v_{i_1}\f$ and \f$k + 1 = v_{i_2}\f$ of these containers holds \f$i_1 < i_2\f$.
1427     *
1428     * Supported parameters for the adapted array (indices and values) are \c unbounded_array<> ,
1429     * \c bounded_array<> and \c std::vector<>.
1430     *
1431     * \tparam T the type of object stored in the vector (like double, float, complex, etc...)
1432     * \tparam IB the index base of the compressed vector. Default is 0. Other supported value is 1
1433     * \tparam IA the type of adapted array for indices. Default is \c unbounded_array<std::size_t>
1434     * \tparam TA the type of adapted array for values. Default is unbounded_array<T>
1435     */
1436    template<class T, std::size_t IB, class IA, class TA>
1437    class coordinate_vector:
1438        public vector_container<coordinate_vector<T, IB, IA, TA> > {
1439
1440        typedef T &true_reference;
1441        typedef T *pointer;
1442        typedef const T *const_pointer;
1443        typedef coordinate_vector<T, IB, IA, TA> self_type;
1444    public:
1445#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1446        using vector_container<self_type>::operator ();
1447#endif
1448        // ISSUE require type consistency check
1449        // is_convertable (IA::size_type, TA::size_type)
1450        typedef typename IA::value_type size_type;
1451        typedef typename IA::difference_type difference_type;
1452        typedef T value_type;
1453        typedef const T &const_reference;
1454#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
1455        typedef T &reference;
1456#else
1457        typedef sparse_vector_element<self_type> reference;
1458#endif
1459        typedef IA index_array_type;
1460        typedef TA value_array_type;
1461        typedef const vector_reference<const self_type> const_closure_type;
1462        typedef vector_reference<self_type> closure_type;
1463        typedef self_type vector_temporary_type;
1464        typedef sparse_tag storage_category;
1465
1466        // Construction and destruction
1467        BOOST_UBLAS_INLINE
1468        coordinate_vector ():
1469            vector_container<self_type> (),
1470            size_ (0), capacity_ (restrict_capacity (0)),
1471            filled_ (0), sorted_filled_ (filled_), sorted_ (true),
1472            index_data_ (capacity_), value_data_ (capacity_) {
1473            storage_invariants ();
1474        }
1475        explicit BOOST_UBLAS_INLINE
1476        coordinate_vector (size_type size, size_type non_zeros = 0):
1477            vector_container<self_type> (),
1478            size_ (size), capacity_ (restrict_capacity (non_zeros)),
1479            filled_ (0), sorted_filled_ (filled_), sorted_ (true),
1480            index_data_ (capacity_), value_data_ (capacity_) {
1481            storage_invariants ();
1482        }
1483        BOOST_UBLAS_INLINE
1484        coordinate_vector (const coordinate_vector &v):
1485            vector_container<self_type> (),
1486            size_ (v.size_), capacity_ (v.capacity_),
1487            filled_ (v.filled_), sorted_filled_ (v.sorted_filled_), sorted_ (v.sorted_),
1488            index_data_ (v.index_data_), value_data_ (v.value_data_) {
1489            storage_invariants ();
1490        }
1491        template<class AE>
1492        BOOST_UBLAS_INLINE
1493        coordinate_vector (const vector_expression<AE> &ae, size_type non_zeros = 0):
1494            vector_container<self_type> (),
1495            size_ (ae ().size ()), capacity_ (restrict_capacity (non_zeros)),
1496            filled_ (0), sorted_filled_ (filled_), sorted_ (true),
1497            index_data_ (capacity_), value_data_ (capacity_) {
1498            storage_invariants ();
1499            vector_assign<scalar_assign> (*this, ae);
1500        }
1501
1502        // Accessors
1503        BOOST_UBLAS_INLINE
1504        size_type size () const {
1505            return size_;
1506        }
1507        BOOST_UBLAS_INLINE
1508        size_type nnz_capacity () const {
1509            return capacity_;
1510        }
1511        BOOST_UBLAS_INLINE
1512        size_type nnz () const {
1513            return filled_;
1514        }
1515
1516        // Storage accessors
1517        BOOST_UBLAS_INLINE
1518        static size_type index_base () {
1519            return IB;
1520        }
1521        BOOST_UBLAS_INLINE
1522        typename index_array_type::size_type filled () const {
1523            return filled_;
1524        }
1525        BOOST_UBLAS_INLINE
1526        const index_array_type &index_data () const {
1527            return index_data_;
1528        }
1529        BOOST_UBLAS_INLINE
1530        const value_array_type &value_data () const {
1531            return value_data_;
1532        }
1533        BOOST_UBLAS_INLINE
1534        void set_filled (const typename index_array_type::size_type &sorted, const typename index_array_type::size_type &filled) {
1535            sorted_filled_ = sorted;
1536            filled_ = filled;
1537            storage_invariants ();
1538        }
1539        BOOST_UBLAS_INLINE
1540        index_array_type &index_data () {
1541            return index_data_;
1542        }
1543        BOOST_UBLAS_INLINE
1544        value_array_type &value_data () {
1545            return value_data_;
1546        }
1547
1548        // Resizing
1549    private:
1550        BOOST_UBLAS_INLINE
1551        size_type restrict_capacity (size_type non_zeros) const {
1552             // minimum non_zeros
1553             non_zeros = (std::max) (non_zeros, size_type (1));
1554             // ISSUE no maximum as coordinate may contain inserted duplicates
1555             return non_zeros;
1556        }
1557    public:
1558        BOOST_UBLAS_INLINE
1559        void resize (size_type size, bool preserve = true) {
1560            if (preserve)
1561                sort ();    // remove duplicate elements.
1562            size_ = size;
1563            capacity_ = restrict_capacity (capacity_);
1564            if (preserve) {
1565                index_data_. resize (capacity_, size_type ());
1566                value_data_. resize (capacity_, value_type ());
1567                filled_ = (std::min) (capacity_, filled_);
1568                while ((filled_ > 0) && (zero_based(index_data_[filled_ - 1]) >= size)) {
1569                    --filled_;
1570                }
1571            }
1572            else {
1573                index_data_. resize (capacity_);
1574                value_data_. resize (capacity_);
1575                filled_ = 0;
1576            }
1577            sorted_filled_ = filled_;
1578            storage_invariants ();
1579        }
1580        // Reserving
1581        BOOST_UBLAS_INLINE
1582        void reserve (size_type non_zeros, bool preserve = true) {
1583            if (preserve)
1584                sort ();    // remove duplicate elements.
1585            capacity_ = restrict_capacity (non_zeros);
1586            if (preserve) {
1587                index_data_. resize (capacity_, size_type ());
1588                value_data_. resize (capacity_, value_type ());
1589                filled_ = (std::min) (capacity_, filled_);
1590                }
1591            else {
1592                index_data_. resize (capacity_);
1593                value_data_. resize (capacity_);
1594                filled_ = 0;
1595            }
1596            sorted_filled_ = filled_;
1597            storage_invariants ();
1598        }
1599
1600        // Element support
1601        BOOST_UBLAS_INLINE
1602        pointer find_element (size_type i) {
1603            return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
1604        }
1605        BOOST_UBLAS_INLINE
1606        const_pointer find_element (size_type i) const {
1607            sort ();
1608            const_subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
1609            if (it == index_data_.begin () + filled_ || *it != k_based (i))
1610                return 0;
1611            return &value_data_ [it - index_data_.begin ()];
1612        }
1613
1614        // Element access
1615        BOOST_UBLAS_INLINE
1616        const_reference operator () (size_type i) const {
1617            BOOST_UBLAS_CHECK (i < size_, bad_index ());
1618            sort ();
1619            const_subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
1620            if (it == index_data_.begin () + filled_ || *it != k_based (i))
1621                return zero_;
1622            return value_data_ [it - index_data_.begin ()];
1623        }
1624        BOOST_UBLAS_INLINE
1625        true_reference ref (size_type i) {
1626            BOOST_UBLAS_CHECK (i < size_, bad_index ());
1627            sort ();
1628            subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
1629            if (it == index_data_.begin () + filled_ || *it != k_based (i))
1630                return insert_element (i, value_type/*zero*/());
1631            else
1632                return value_data_ [it - index_data_.begin ()];
1633        }
1634        BOOST_UBLAS_INLINE
1635        reference operator () (size_type i) {
1636#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
1637            return ref (i);
1638#else
1639            BOOST_UBLAS_CHECK (i < size_, bad_index ());
1640            return reference (*this, i);
1641#endif
1642        }
1643
1644        BOOST_UBLAS_INLINE
1645        const_reference operator [] (size_type i) const {
1646            return (*this) (i);
1647        }
1648        BOOST_UBLAS_INLINE
1649        reference operator [] (size_type i) {
1650            return (*this) (i);
1651        }
1652
1653        // Element assignment
1654        BOOST_UBLAS_INLINE
1655        void append_element (size_type i, const_reference t) {
1656            if (filled_ >= capacity_)
1657                reserve (2 * filled_, true);
1658            BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
1659            index_data_ [filled_] = k_based (i);
1660            value_data_ [filled_] = t;
1661            ++ filled_;
1662            sorted_ = false;
1663            storage_invariants ();
1664        }
1665        BOOST_UBLAS_INLINE
1666        true_reference insert_element (size_type i, const_reference t) {
1667            BOOST_UBLAS_CHECK (!find_element (i), bad_index ());        // duplicate element
1668            append_element (i, t);
1669            return value_data_ [filled_ - 1];
1670        }
1671        BOOST_UBLAS_INLINE
1672        void erase_element (size_type i) {
1673            sort ();
1674            subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
1675            typename std::iterator_traits<subiterator_type>::difference_type n = it - index_data_.begin ();
1676            if (filled_ > typename index_array_type::size_type (n) && *it == k_based (i)) {
1677                std::copy (it + 1, index_data_.begin () + filled_, it);
1678                typename value_array_type::iterator itt (value_data_.begin () + n);
1679                std::copy (itt + 1, value_data_.begin () + filled_, itt);
1680                -- filled_;
1681                sorted_filled_ = filled_;
1682            }
1683            storage_invariants ();
1684        }
1685
1686        // Zeroing
1687        BOOST_UBLAS_INLINE
1688        void clear () {
1689            filled_ = 0;
1690            sorted_filled_ = filled_;
1691            sorted_ = true;
1692            storage_invariants ();
1693        }
1694
1695        // Assignment
1696        BOOST_UBLAS_INLINE
1697        coordinate_vector &operator = (const coordinate_vector &v) {
1698            if (this != &v) {
1699                size_ = v.size_;
1700                capacity_ = v.capacity_;
1701                filled_ = v.filled_;
1702                sorted_filled_ = v.sorted_filled_;
1703                sorted_ = v.sorted_;
1704                index_data_ = v.index_data_;
1705                value_data_ = v.value_data_;
1706            }
1707            storage_invariants ();
1708            return *this;
1709        }
1710        template<class C>          // Container assignment without temporary
1711        BOOST_UBLAS_INLINE
1712        coordinate_vector &operator = (const vector_container<C> &v) {
1713            resize (v ().size (), false);
1714            assign (v);
1715            return *this;
1716        }
1717        BOOST_UBLAS_INLINE
1718        coordinate_vector &assign_temporary (coordinate_vector &v) {
1719            swap (v);
1720            return *this;
1721        }
1722        template<class AE>
1723        BOOST_UBLAS_INLINE
1724        coordinate_vector &operator = (const vector_expression<AE> &ae) {
1725            self_type temporary (ae, capacity_);
1726            return assign_temporary (temporary);
1727        }
1728        template<class AE>
1729        BOOST_UBLAS_INLINE
1730        coordinate_vector &assign (const vector_expression<AE> &ae) {
1731            vector_assign<scalar_assign> (*this, ae);
1732            return *this;
1733        }
1734
1735        // Computed assignment
1736        template<class AE>
1737        BOOST_UBLAS_INLINE
1738        coordinate_vector &operator += (const vector_expression<AE> &ae) {
1739            self_type temporary (*this + ae, capacity_);
1740            return assign_temporary (temporary);
1741        }
1742        template<class C>          // Container assignment without temporary
1743        BOOST_UBLAS_INLINE
1744        coordinate_vector &operator += (const vector_container<C> &v) {
1745            plus_assign (v);
1746            return *this;
1747        }
1748        template<class AE>
1749        BOOST_UBLAS_INLINE
1750        coordinate_vector &plus_assign (const vector_expression<AE> &ae) {
1751            vector_assign<scalar_plus_assign> (*this, ae);
1752            return *this;
1753        }
1754        template<class AE>
1755        BOOST_UBLAS_INLINE
1756        coordinate_vector &operator -= (const vector_expression<AE> &ae) {
1757            self_type temporary (*this - ae, capacity_);
1758            return assign_temporary (temporary);
1759        }
1760        template<class C>          // Container assignment without temporary
1761        BOOST_UBLAS_INLINE
1762        coordinate_vector &operator -= (const vector_container<C> &v) {
1763            minus_assign (v);
1764            return *this;
1765        }
1766        template<class AE>
1767        BOOST_UBLAS_INLINE
1768        coordinate_vector &minus_assign (const vector_expression<AE> &ae) {
1769            vector_assign<scalar_minus_assign> (*this, ae);
1770            return *this;
1771        }
1772        template<class AT>
1773        BOOST_UBLAS_INLINE
1774        coordinate_vector &operator *= (const AT &at) {
1775            vector_assign_scalar<scalar_multiplies_assign> (*this, at);
1776            return *this;
1777        }
1778        template<class AT>
1779        BOOST_UBLAS_INLINE
1780        coordinate_vector &operator /= (const AT &at) {
1781            vector_assign_scalar<scalar_divides_assign> (*this, at);
1782            return *this;
1783        }
1784
1785        // Swapping
1786        BOOST_UBLAS_INLINE
1787        void swap (coordinate_vector &v) {
1788            if (this != &v) {
1789                std::swap (size_, v.size_);
1790                std::swap (capacity_, v.capacity_);
1791                std::swap (filled_, v.filled_);
1792                std::swap (sorted_filled_, v.sorted_filled_);
1793                std::swap (sorted_, v.sorted_);
1794                index_data_.swap (v.index_data_);
1795                value_data_.swap (v.value_data_);
1796            }
1797            storage_invariants ();
1798        }
1799        BOOST_UBLAS_INLINE
1800        friend void swap (coordinate_vector &v1, coordinate_vector &v2) {
1801            v1.swap (v2);
1802        }
1803
1804        // Sorting and summation of duplicates
1805        BOOST_UBLAS_INLINE
1806        void sort () const {
1807            if (! sorted_ && filled_ > 0) {
1808                typedef index_pair_array<index_array_type, value_array_type> array_pair;
1809                array_pair ipa (filled_, index_data_, value_data_);
1810                const typename array_pair::iterator iunsorted = ipa.begin () + sorted_filled_;
1811                // sort new elements and merge
1812                std::sort (iunsorted, ipa.end ());
1813                std::inplace_merge (ipa.begin (), iunsorted, ipa.end ());
1814
1815                // sum duplicates with += and remove
1816                size_type filled = 0;
1817                for (size_type i = 1; i < filled_; ++ i) {
1818                    if (index_data_ [filled] != index_data_ [i]) {
1819                        ++ filled;
1820                        if (filled != i) {
1821                            index_data_ [filled] = index_data_ [i];
1822                            value_data_ [filled] = value_data_ [i];
1823                        }
1824                    } else {
1825                        value_data_ [filled] += value_data_ [i];
1826                    }
1827                }
1828                filled_ = filled + 1;
1829                sorted_filled_ = filled_;
1830                sorted_ = true;
1831                storage_invariants ();
1832            }
1833        }
1834
1835        // Back element insertion and erasure
1836        BOOST_UBLAS_INLINE
1837        void push_back (size_type i, const_reference t) {
1838            // must maintain sort order
1839            BOOST_UBLAS_CHECK (sorted_ && (filled_ == 0 || index_data_ [filled_ - 1] < k_based (i)), external_logic ());
1840            if (filled_ >= capacity_)
1841                reserve (2 * filled_, true);
1842            BOOST_UBLAS_CHECK (filled_ < capacity_, internal_logic ());
1843            index_data_ [filled_] = k_based (i);
1844            value_data_ [filled_] = t;
1845            ++ filled_;
1846            sorted_filled_ = filled_;
1847            storage_invariants ();
1848        }
1849        BOOST_UBLAS_INLINE
1850        void pop_back () {
1851            // ISSUE invariants could be simpilfied if sorted required as precondition
1852            BOOST_UBLAS_CHECK (filled_ > 0, external_logic ());
1853            -- filled_;
1854            sorted_filled_ = (std::min) (sorted_filled_, filled_);
1855            sorted_ = sorted_filled_ = filled_;
1856            storage_invariants ();
1857        }
1858
1859        // Iterator types
1860    private:
1861        // Use index array iterator
1862        typedef typename IA::const_iterator const_subiterator_type;
1863        typedef typename IA::iterator subiterator_type;
1864
1865        BOOST_UBLAS_INLINE
1866        true_reference at_element (size_type i) {
1867            BOOST_UBLAS_CHECK (i < size_, bad_index ());
1868            sort ();
1869            subiterator_type it (detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
1870            BOOST_UBLAS_CHECK (it != index_data_.begin () + filled_ && *it == k_based (i), bad_index ());
1871            return value_data_ [it - index_data_.begin ()];
1872        }
1873
1874    public:
1875        class const_iterator;
1876        class iterator;
1877
1878        // Element lookup
1879        // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1880        const_iterator find (size_type i) const {
1881            sort ();
1882            return const_iterator (*this, detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
1883        }
1884        // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
1885        iterator find (size_type i) {
1886            sort ();
1887            return iterator (*this, detail::lower_bound (index_data_.begin (), index_data_.begin () + filled_, k_based (i), std::less<size_type> ()));
1888        }
1889
1890
1891        class const_iterator:
1892            public container_const_reference<coordinate_vector>,
1893            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
1894                                               const_iterator, value_type> {
1895        public:
1896            typedef typename coordinate_vector::value_type value_type;
1897            typedef typename coordinate_vector::difference_type difference_type;
1898            typedef typename coordinate_vector::const_reference reference;
1899            typedef const typename coordinate_vector::pointer pointer;
1900
1901            // Construction and destruction
1902            BOOST_UBLAS_INLINE
1903            const_iterator ():
1904                container_const_reference<self_type> (), it_ () {}
1905            BOOST_UBLAS_INLINE
1906            const_iterator (const self_type &v, const const_subiterator_type &it):
1907                container_const_reference<self_type> (v), it_ (it) {}
1908            BOOST_UBLAS_INLINE
1909            const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
1910                container_const_reference<self_type> (it ()), it_ (it.it_) {}
1911
1912            // Arithmetic
1913            BOOST_UBLAS_INLINE
1914            const_iterator &operator ++ () {
1915                ++ it_;
1916                return *this;
1917            }
1918            BOOST_UBLAS_INLINE
1919            const_iterator &operator -- () {
1920                -- it_;
1921                return *this;
1922            }
1923
1924            // Dereference
1925            BOOST_UBLAS_INLINE
1926            const_reference operator * () const {
1927                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1928                return (*this) ().value_data_ [it_ - (*this) ().index_data_.begin ()];
1929            }
1930
1931            // Index
1932            BOOST_UBLAS_INLINE
1933            size_type index () const {
1934                BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
1935                BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
1936                return (*this) ().zero_based (*it_);
1937            }
1938
1939            // Assignment
1940            BOOST_UBLAS_INLINE
1941            const_iterator &operator = (const const_iterator &it) {
1942                container_const_reference<self_type>::assign (&it ());
1943                it_ = it.it_;
1944                return *this;
1945            }
1946
1947            // Comparison
1948            BOOST_UBLAS_INLINE
1949            bool operator == (const const_iterator &it) const {
1950                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1951                return it_ == it.it_;
1952            }
1953
1954        private:
1955            const_subiterator_type it_;
1956        };
1957
1958        BOOST_UBLAS_INLINE
1959        const_iterator begin () const {
1960            return find (0);
1961        }
1962        BOOST_UBLAS_INLINE
1963        const_iterator end () const {
1964            return find (size_);
1965        }
1966
1967        class iterator:
1968            public container_reference<coordinate_vector>,
1969            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
1970                                               iterator, value_type> {
1971        public:
1972            typedef typename coordinate_vector::value_type value_type;
1973            typedef typename coordinate_vector::difference_type difference_type;
1974            typedef typename coordinate_vector::true_reference reference;
1975            typedef typename coordinate_vector::pointer pointer;
1976
1977            // Construction and destruction
1978            BOOST_UBLAS_INLINE
1979            iterator ():
1980                container_reference<self_type> (), it_ () {}
1981            BOOST_UBLAS_INLINE
1982            iterator (self_type &v, const subiterator_type &it):
1983                container_reference<self_type> (v), it_ (it) {}
1984
1985            // Arithmetic
1986            BOOST_UBLAS_INLINE
1987            iterator &operator ++ () {
1988                ++ it_;
1989                return *this;
1990            }
1991            BOOST_UBLAS_INLINE
1992            iterator &operator -- () {
1993                -- it_;
1994                return *this;
1995            }
1996
1997            // Dereference
1998            BOOST_UBLAS_INLINE
1999            reference operator * () const {
2000                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
2001                return (*this) ().value_data_ [it_ - (*this) ().index_data_.begin ()];
2002            }
2003
2004            // Index
2005            BOOST_UBLAS_INLINE
2006            size_type index () const {
2007                BOOST_UBLAS_CHECK (*this != (*this) ().end (), bad_index ());
2008                BOOST_UBLAS_CHECK ((*this) ().zero_based (*it_) < (*this) ().size (), bad_index ());
2009                return (*this) ().zero_based (*it_);
2010            }
2011
2012            // Assignment
2013            BOOST_UBLAS_INLINE
2014            iterator &operator = (const iterator &it) {
2015                container_reference<self_type>::assign (&it ());
2016                it_ = it.it_;
2017                return *this;
2018            }
2019
2020            // Comparison
2021            BOOST_UBLAS_INLINE
2022            bool operator == (const iterator &it) const {
2023                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2024                return it_ == it.it_;
2025            }
2026
2027        private:
2028            subiterator_type it_;
2029
2030            friend class const_iterator;
2031        };
2032
2033        BOOST_UBLAS_INLINE
2034        iterator begin () {
2035            return find (0);
2036        }
2037        BOOST_UBLAS_INLINE
2038        iterator end () {
2039            return find (size_);
2040        }
2041
2042        // Reverse iterator
2043        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
2044        typedef reverse_iterator_base<iterator> reverse_iterator;
2045
2046        BOOST_UBLAS_INLINE
2047        const_reverse_iterator rbegin () const {
2048            return const_reverse_iterator (end ());
2049        }
2050        BOOST_UBLAS_INLINE
2051        const_reverse_iterator rend () const {
2052            return const_reverse_iterator (begin ());
2053        }
2054        BOOST_UBLAS_INLINE
2055        reverse_iterator rbegin () {
2056            return reverse_iterator (end ());
2057        }
2058        BOOST_UBLAS_INLINE
2059        reverse_iterator rend () {
2060            return reverse_iterator (begin ());
2061        }
2062
2063         // Serialization
2064        template<class Archive>
2065        void serialize(Archive & ar, const unsigned int /* file_version */){
2066            serialization::collection_size_type s (size_);
2067            ar & serialization::make_nvp("size",s);
2068            if (Archive::is_loading::value) {
2069                size_ = s;
2070            }
2071            // ISSUE: filled may be much less than capacity
2072            // ISSUE: index_data_ and value_data_ are undefined between filled and capacity (trouble with 'nan'-values)
2073            ar & serialization::make_nvp("capacity", capacity_);
2074            ar & serialization::make_nvp("filled", filled_);
2075            ar & serialization::make_nvp("sorted_filled", sorted_filled_);
2076            ar & serialization::make_nvp("sorted", sorted_);
2077            ar & serialization::make_nvp("index_data", index_data_);
2078            ar & serialization::make_nvp("value_data", value_data_);
2079            storage_invariants();
2080        }
2081
2082    private:
2083        void storage_invariants () const
2084        {
2085            BOOST_UBLAS_CHECK (capacity_ == index_data_.size (), internal_logic ());
2086            BOOST_UBLAS_CHECK (capacity_ == value_data_.size (), internal_logic ());
2087            BOOST_UBLAS_CHECK (filled_ <= capacity_, internal_logic ());
2088            BOOST_UBLAS_CHECK (sorted_filled_ <= filled_, internal_logic ());
2089            BOOST_UBLAS_CHECK (sorted_ == (sorted_filled_ == filled_), internal_logic ());
2090            BOOST_UBLAS_CHECK ((0 == filled_) || (zero_based(index_data_[filled_ - 1]) < size_), internal_logic ());
2091        }
2092
2093        size_type size_;
2094        size_type capacity_;
2095        mutable typename index_array_type::size_type filled_;
2096        mutable typename index_array_type::size_type sorted_filled_;
2097        mutable bool sorted_;
2098        mutable index_array_type index_data_;
2099        mutable value_array_type value_data_;
2100        static const value_type zero_;
2101
2102        BOOST_UBLAS_INLINE
2103        static size_type zero_based (size_type k_based_index) {
2104            return k_based_index - IB;
2105        }
2106        BOOST_UBLAS_INLINE
2107        static size_type k_based (size_type zero_based_index) {
2108            return zero_based_index + IB;
2109        }
2110
2111        friend class iterator;
2112        friend class const_iterator;
2113    };
2114
2115    template<class T, std::size_t IB, class IA, class TA>
2116    const typename coordinate_vector<T, IB, IA, TA>::value_type coordinate_vector<T, IB, IA, TA>::zero_ = value_type/*zero*/();
2117
2118}}}
2119
2120#endif
Note: See TracBrowser for help on using the repository browser.