source: NonGTP/Boost/boost/numeric/ublas/vector_of_vector.hpp @ 857

Revision 857, 50.2 KB checked in by igarcia, 18 years ago (diff)
Line 
1//
2//  Copyright (c) 2003
3//  Gunter Winkler, Joerg Walter
4//
5//  Permission to use, copy, modify, distribute and sell this software
6//  and its documentation for any purpose is hereby granted without fee,
7//  provided that the above copyright notice appear in all copies and
8//  that both that copyright notice and this permission notice appear
9//  in supporting documentation.  The authors make no representations
10//  about the suitability of this software for any purpose.
11//  It is provided "as is" without express or implied warranty.
12//
13//  The authors gratefully acknowledge the support of
14//  GeNeSys mbH & Co. KG in producing this work.
15//
16
17#ifndef _BOOST_UBLAS_VECTOR_OF_VECTOR_
18#define _BOOST_UBLAS_VECTOR_OF_VECTOR_
19
20#include <boost/type_traits.hpp>
21
22#include <boost/numeric/ublas/storage_sparse.hpp>
23#include <boost/numeric/ublas/matrix_sparse.hpp>
24
25// Iterators based on ideas of Jeremy Siek
26
27namespace boost { namespace numeric { namespace ublas {
28
29    // uBLAS sparse vector based sparse matrix class
30    // FIXME outer vector can be sparse type but it is completely filled
31    template<class T, class L, class A>
32    class generalized_vector_of_vector:
33        public matrix_container<generalized_vector_of_vector<T, L, A> > {
34
35        typedef T &true_reference;
36        typedef T *pointer;
37        typedef const T *const_pointer;
38        typedef L layout_type;
39        typedef generalized_vector_of_vector<T, L, A> self_type;
40    public:
41#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
42        using matrix_container<self_type>::operator ();
43#endif
44        typedef typename A::size_type size_type;
45        typedef typename A::difference_type difference_type;
46        typedef T value_type;
47        typedef const T &const_reference;
48#ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
49        typedef T &reference;
50#else
51        typedef sparse_matrix_element<self_type> reference;
52#endif
53        typedef A array_type;
54        typedef const matrix_reference<const self_type> const_closure_type;
55        typedef matrix_reference<self_type> closure_type;
56        typedef typename A::value_type vector_data_value_type;
57        typedef vector_data_value_type vector_temporary_type;
58        typedef self_type matrix_temporary_type;
59        typedef sparse_tag storage_category;
60        typedef typename L::orientation_category orientation_category;
61
62        // Construction and destruction
63        BOOST_UBLAS_INLINE
64        generalized_vector_of_vector ():
65            matrix_container<self_type> (),
66            size1_ (0), size2_ (0), data_ (1) {
67            const size_type sizeM = layout_type::size1 (size1_, size2_);
68             // create size1+1 empty vector elements
69            data_.insert_element (sizeM, vector_data_value_type ());
70            storage_invariants ();
71        }
72        BOOST_UBLAS_INLINE
73        generalized_vector_of_vector (size_type size1, size_type size2, size_type non_zeros = 0):
74            matrix_container<self_type> (),
75            size1_ (size1), size2_ (size2), data_ (layout_type::size1 (size1_, size2_) + 1) {
76            const size_type sizeM = layout_type::size1 (size1_, size2_);
77            const size_type sizem = layout_type::size2 (size1_, size2_);
78            for (size_type i = 0; i < sizeM; ++ i) // create size1 vector elements
79                data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
80            data_.insert_element (sizeM, vector_data_value_type ());
81            storage_invariants ();
82        }
83        BOOST_UBLAS_INLINE
84        generalized_vector_of_vector (const generalized_vector_of_vector &m):
85            matrix_container<self_type> (),
86            size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {
87            storage_invariants ();
88        }
89        template<class AE>
90        BOOST_UBLAS_INLINE
91        generalized_vector_of_vector (const matrix_expression<AE> &ae, size_type non_zeros = 0):
92            matrix_container<self_type> (),
93            size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size1 (size1_, size2_) + 1) {
94            const size_type sizeM = layout_type::size1 (size1_, size2_);
95            const size_type sizem = layout_type::size2 (size1_, size2_);
96            for (size_type i = 0; i < sizeM; ++ i) // create size1 vector elements
97                data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
98            data_.insert_element (sizeM, vector_data_value_type ());
99            storage_invariants ();
100            matrix_assign<scalar_assign> (*this, ae);
101        }
102
103        // Accessors
104        BOOST_UBLAS_INLINE
105        size_type size1 () const {
106            return size1_;
107        }
108        BOOST_UBLAS_INLINE
109        size_type size2 () const {
110            return size2_;
111        }
112        BOOST_UBLAS_INLINE
113        size_type non_zeros () const {
114            size_type non_zeros = 0;
115            for (const_vectoriterator_type itv = data_ ().begin (); itv != data_ ().end (); ++ itv)
116                non_zeros += (*itv).size ();
117            return non_zeros;
118        }
119
120        // Storage accessors
121        BOOST_UBLAS_INLINE
122        const array_type &data () const {
123            return data_;
124        }
125        BOOST_UBLAS_INLINE
126        array_type &data () {
127            return data_;
128        }
129
130        // Resizing
131        BOOST_UBLAS_INLINE
132        void resize (size_type size1, size_type size2, bool preserve = true) {
133            const size_type oldM = layout_type::size1 (size1_, size2_);
134            size1_ = size1;
135            size2_ = size2;
136            const size_type sizeM = layout_type::size1 (size1_, size2_);
137            const size_type sizem = layout_type::size2 (size1_, size2_);
138            data ().resize (sizeM + 1, preserve);
139            if (preserve) {
140                for (size_type i = 0; (i <= oldM) && (i < sizeM); ++ i)
141                    ref (data () [i]).resize (sizem, preserve);
142                for (size_type i = oldM+1; i < sizeM; ++ i) // create new vector elements
143                    data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
144                if (sizeM > oldM) {
145                    data_.insert_element (sizeM, vector_data_value_type ());
146                } else {
147                    ref (data () [sizeM]).resize (0, false);
148                }
149            } else {
150                for (size_type i = 0; i < sizeM; ++ i)
151                    data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
152                data_.insert_element (sizeM, vector_data_value_type ());
153            }
154            storage_invariants ();
155        }
156
157        // Element support
158        BOOST_UBLAS_INLINE
159        pointer find_element (size_type i, size_type j) {
160            return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
161        }
162        BOOST_UBLAS_INLINE
163        const_pointer find_element (size_type i, size_type j) const {
164            const size_type elementM = layout_type::element1 (i, size1_, j, size2_);
165            const size_type elementm = layout_type::element2 (i, size1_, j, size2_);
166            // optimise: check the storage_type and index directly if element always exists
167            if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) {
168                return & (data () [elementM] [elementm]);
169            }
170            else {
171                const typename array_type::value_type *pv = data ().find_element (elementM);
172                if (!pv)
173                    return 0;
174                return pv->find_element (elementm);
175            }
176        }
177
178        // Element access
179        BOOST_UBLAS_INLINE
180        const_reference operator () (size_type i, size_type j) const {
181            const_pointer p = find_element (i, j);
182            // optimise: check the storage_type and index directly if element always exists
183            if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) {
184                BOOST_UBLAS_CHECK (p, internal_logic () );
185                return *p;
186            }
187            else {
188                if (p)
189                    return *p;
190                else
191                    return zero_;
192            }
193        }
194        BOOST_UBLAS_INLINE
195        reference operator () (size_type i, size_type j) {
196#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
197            return at_element (i, j);
198#else
199            return reference (*this, i, j);
200#endif
201        }
202
203        // Assignment
204        BOOST_UBLAS_INLINE
205        generalized_vector_of_vector &operator = (const generalized_vector_of_vector &m) {
206            if (this != &m) {
207                size1_ = m.size1_;
208                size2_ = m.size2_;
209                data () = m.data ();
210            }
211            storage_invariants ();
212            return *this;
213        }
214        BOOST_UBLAS_INLINE
215        generalized_vector_of_vector &assign_temporary (generalized_vector_of_vector &m) {
216            swap (m);
217            return *this;
218        }
219        template<class AE>
220        BOOST_UBLAS_INLINE
221        generalized_vector_of_vector &operator = (const matrix_expression<AE> &ae) {
222            self_type temporary (ae);
223            return assign_temporary (temporary);
224        }
225        template<class AE>
226        BOOST_UBLAS_INLINE
227        generalized_vector_of_vector &assign (const matrix_expression<AE> &ae) {
228            matrix_assign<scalar_assign> (*this, ae);
229            return *this;
230        }
231        template<class AE>
232        BOOST_UBLAS_INLINE
233        generalized_vector_of_vector& operator += (const matrix_expression<AE> &ae) {
234            self_type temporary (*this + ae);
235            return assign_temporary (temporary);
236        }
237        template<class AE>
238        BOOST_UBLAS_INLINE
239        generalized_vector_of_vector &plus_assign (const matrix_expression<AE> &ae) {
240            matrix_assign<scalar_plus_assign> (*this, ae);
241            return *this;
242        }
243        template<class AE>
244        BOOST_UBLAS_INLINE
245        generalized_vector_of_vector& operator -= (const matrix_expression<AE> &ae) {
246            self_type temporary (*this - ae);
247            return assign_temporary (temporary);
248        }
249        template<class AE>
250        BOOST_UBLAS_INLINE
251        generalized_vector_of_vector &minus_assign (const matrix_expression<AE> &ae) {
252            matrix_assign<scalar_minus_assign> (*this, ae);
253            return *this;
254        }
255        template<class AT>
256        BOOST_UBLAS_INLINE
257        generalized_vector_of_vector& operator *= (const AT &at) {
258            matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
259            return *this;
260        }
261        template<class AT>
262        BOOST_UBLAS_INLINE
263        generalized_vector_of_vector& operator /= (const AT &at) {
264            matrix_assign_scalar<scalar_divides_assign> (*this, at);
265            return *this;
266        }
267
268        // Swapping
269        BOOST_UBLAS_INLINE
270        void swap (generalized_vector_of_vector &m) {
271            if (this != &m) {
272                std::swap (size1_, m.size1_);
273                std::swap (size2_, m.size2_);
274                data ().swap (m.data ());
275            }
276            storage_invariants ();
277        }
278        BOOST_UBLAS_INLINE
279        friend void swap (generalized_vector_of_vector &m1, generalized_vector_of_vector &m2) {
280            m1.swap (m2);
281        }
282
283        // Sorting
284        void sort () {
285            vectoriterator_type itv (data ().begin ());
286            vectoriterator_type itv_end (data ().end ());
287            while (itv != itv_end) {
288                (*itv).sort ();
289                ++ itv;
290            }
291        }
292
293        // Element insertion and erasure
294        BOOST_UBLAS_INLINE
295        true_reference insert_element (size_type i, size_type j, const_reference t) {
296            const size_type elementM = layout_type::element1 (i, size1_, j, size2_);
297            const size_type elementm = layout_type::element2 (i, size1_, j, size2_);
298            vector_data_value_type& vd (ref (data () [elementM]));
299            storage_invariants ();
300            return vd.insert_element (elementm, t);
301        }
302        BOOST_UBLAS_INLINE
303        void append_element (size_type i, size_type j, const_reference t) {
304            const size_type elementM = layout_type::element1 (i, size1_, j, size2_);
305            const size_type elementm = layout_type::element2 (i, size1_, j, size2_);
306            vector_data_value_type& vd (ref (data () [elementM]));
307            storage_invariants ();
308            return vd.append_element (elementm, t);
309        }
310        BOOST_UBLAS_INLINE
311        void erase_element (size_type i, size_type j) {
312            vectoriterator_type itv (data ().find (layout_type::element1 (i, size1_, j, size2_)));
313            if (itv == data ().end ())
314                return;
315            (*itv).erase_element (layout_type::element2 (i, size1_, j, size2_));
316            storage_invariants ();
317        }
318        BOOST_UBLAS_INLINE
319        void clear () {
320            const size_type sizeM = layout_type::size1 (size1_, size2_);
321            // FIXME should clear data () if this is done via value_type/*zero*/() then it is not size preserving
322            for (size_type i = 0; i < sizeM; ++ i)
323                ref (data () [i]).clear ();
324            storage_invariants ();
325        }
326
327        // Iterator types
328    private:
329        // Use vector iterator
330        typedef typename A::const_iterator const_vectoriterator_type;
331        typedef typename A::iterator vectoriterator_type;
332        typedef typename A::value_type::const_iterator const_subiterator_type;
333        typedef typename A::value_type::iterator subiterator_type;
334
335        BOOST_UBLAS_INLINE
336        true_reference at_element (size_type i, size_type j) {
337            return ref (ref (data () [layout_type::element1 (i, size1_, j, size2_)]) [layout_type::element2 (i, size1_, j, size2_)]);
338        }
339
340    public:
341        class const_iterator1;
342        class iterator1;
343        class const_iterator2;
344        class iterator2;
345        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
346        typedef reverse_iterator_base1<iterator1> reverse_iterator1;
347        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
348        typedef reverse_iterator_base2<iterator2> reverse_iterator2;
349
350        // Element lookup
351        // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.   
352        const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
353            for (;;) {
354                const_vectoriterator_type itv (data ().find (layout_type::address1 (i, size1_, j, size2_)));
355                const_vectoriterator_type itv_end (data ().end ());
356                if (itv == itv_end)
357                    return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
358
359                const_subiterator_type it ((*itv).find (layout_type::address2 (i, size1_, j, size2_)));
360                const_subiterator_type it_end ((*itv).end ());
361                if (rank == 0)
362                    return const_iterator1 (*this, rank, i, j, itv, it);
363                if (it != it_end && it.index () == layout_type::address2 (i, size1_, j, size2_))
364                    return const_iterator1 (*this, rank, i, j, itv, it);
365                if (direction > 0) {
366                    if (layout_type::fast1 ()) {
367                        if (it == it_end)
368                            return const_iterator1 (*this, rank, i, j, itv, it);
369                        i = it.index ();
370                    } else {
371                        if (i >= size1_)
372                            return const_iterator1 (*this, rank, i, j, itv, it);
373                        ++ i;
374                    }
375                } else /* if (direction < 0)  */ {
376                    if (layout_type::fast1 ()) {
377                        if (it == (*itv).begin ())
378                            return const_iterator1 (*this, rank, i, j, itv, it);
379                        --it;
380                        i = it.index ();
381                    } else {
382                        if (i == 0)
383                            return const_iterator1 (*this, rank, i, j, itv, it);
384                        -- i;
385                    }
386                }
387            }
388        }
389        // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.   
390        iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
391            for (;;) {
392                vectoriterator_type itv (data ().find (layout_type::address1 (i, size1_, j, size2_)));
393                vectoriterator_type itv_end (data ().end ());
394                if (itv == itv_end)
395                    return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
396
397                subiterator_type it ((*itv).find (layout_type::address2 (i, size1_, j, size2_)));
398                subiterator_type it_end ((*itv).end ());
399                if (rank == 0)
400                    return iterator1 (*this, rank, i, j, itv, it);
401                if (it != it_end && it.index () == layout_type::address2 (i, size1_, j, size2_))
402                    return iterator1 (*this, rank, i, j, itv, it);
403                if (direction > 0) {
404                    if (layout_type::fast1 ()) {
405                        if (it == it_end)
406                            return iterator1 (*this, rank, i, j, itv, it);
407                        i = it.index ();
408                    } else {
409                        if (i >= size1_)
410                            return iterator1 (*this, rank, i, j, itv, it);
411                        ++ i;
412                    }
413                } else /* if (direction < 0)  */ {
414                    if (layout_type::fast1 ()) {
415                        if (it == (*itv).begin ())
416                            return iterator1 (*this, rank, i, j, itv, it);
417                        --it;
418                        i = it.index ();
419                    } else {
420                        if (i == 0)
421                            return iterator1 (*this, rank, i, j, itv, it);
422                        -- i;
423                    }
424                }
425            }
426        }
427        // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.   
428        const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
429            for (;;) {
430                const_vectoriterator_type itv (data ().find (layout_type::address1 (i, size1_, j, size2_)));
431                const_vectoriterator_type itv_end (data ().end ());
432                if (itv == itv_end)
433                    return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
434
435                const_subiterator_type it ((*itv).find (layout_type::address2 (i, size1_, j, size2_)));
436                const_subiterator_type it_end ((*itv).end ());
437                if (rank == 0)
438                    return const_iterator2 (*this, rank, i, j, itv, it);
439                if (it != it_end && it.index () == layout_type::address2 (i, size1_, j, size2_))
440                    return const_iterator2 (*this, rank, i, j, itv, it);
441                if (direction > 0) {
442                    if (layout_type::fast2 ()) {
443                        if (it == it_end)
444                            return const_iterator2 (*this, rank, i, j, itv, it);
445                        j = it.index ();
446                    } else {
447                        if (j >= size2_)
448                            return const_iterator2 (*this, rank, i, j, itv, it);
449                        ++ j;
450                    }
451                } else /* if (direction < 0)  */ {
452                    if (layout_type::fast2 ()) {
453                        if (it == (*itv).begin ())
454                            return const_iterator2 (*this, rank, i, j, itv, it);
455                        --it;
456                        j = it.index ();
457                    } else {
458                        if (j == 0)
459                            return const_iterator2 (*this, rank, i, j, itv, it);
460                        -- j;
461                    }
462                }
463            }
464        }
465        // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.   
466        iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
467            for (;;) {
468                vectoriterator_type itv (data ().find (layout_type::address1 (i, size1_, j, size2_)));
469                vectoriterator_type itv_end (data ().end ());
470                if (itv == itv_end)
471                    return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
472
473                subiterator_type it ((*itv).find (layout_type::address2 (i, size1_, j, size2_)));
474                subiterator_type it_end ((*itv).end ());
475                if (rank == 0)
476                    return iterator2 (*this, rank, i, j, itv, it);
477                if (it != it_end && it.index () == layout_type::address2 (i, size1_, j, size2_))
478                    return iterator2 (*this, rank, i, j, itv, it);
479                if (direction > 0) {
480                    if (layout_type::fast2 ()) {
481                        if (it == it_end)
482                            return iterator2 (*this, rank, i, j, itv, it);
483                        j = it.index ();
484                    } else {
485                        if (j >= size2_)
486                            return iterator2 (*this, rank, i, j, itv, it);
487                        ++ j;
488                    }
489                } else /* if (direction < 0)  */ {
490                    if (layout_type::fast2 ()) {
491                        if (it == (*itv).begin ())
492                            return iterator2 (*this, rank, i, j, itv, it);
493                        --it;
494                        j = it.index ();
495                    } else {
496                        if (j == 0)
497                            return iterator2 (*this, rank, i, j, itv, it);
498                        -- j;
499                    }
500                }
501            }
502        }
503
504
505        class const_iterator1:
506            public container_const_reference<generalized_vector_of_vector>,
507            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
508                                               const_iterator1, value_type> {
509        public:
510            typedef typename generalized_vector_of_vector::difference_type difference_type;
511            typedef typename generalized_vector_of_vector::value_type value_type;
512            typedef typename generalized_vector_of_vector::const_reference reference;
513            typedef const typename generalized_vector_of_vector::pointer pointer;
514
515            typedef const_iterator2 dual_iterator_type;
516            typedef const_reverse_iterator2 dual_reverse_iterator_type;
517
518            // Construction and destruction
519            BOOST_UBLAS_INLINE
520            const_iterator1 ():
521                container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
522            BOOST_UBLAS_INLINE
523            const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it):
524                container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
525            BOOST_UBLAS_INLINE
526            const_iterator1 (const iterator1 &it):
527                container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
528
529            // Arithmetic
530            BOOST_UBLAS_INLINE
531            const_iterator1 &operator ++ () {
532                if (rank_ == 1 && layout_type::fast1 ())
533                    ++ it_;
534                else {
535                    const self_type &m = (*this) ();
536                    i_ = index1 () + 1;
537                    if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
538                        *this = m.find1 (rank_, i_, j_, 1);
539                    else if (rank_ == 1) {
540                        it_ = (*itv_).begin ();
541                        if (it_ == (*itv_).end () || index2 () != j_)
542                            *this = m.find1 (rank_, i_, j_, 1);
543                    }
544                }
545                return *this;
546            }
547            BOOST_UBLAS_INLINE
548            const_iterator1 &operator -- () {
549                if (rank_ == 1 && layout_type::fast1 ())
550                    -- it_;
551                else {
552                    const self_type &m = (*this) ();
553                    i_ = index1 () - 1;
554                    if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
555                        *this = m.find1 (rank_, i_, j_, -1);
556                    else if (rank_ == 1) {
557                        it_ = (*itv_).begin ();
558                        if (it_ == (*itv_).end () || index2 () != j_)
559                            *this = m.find1 (rank_, i_, j_, -1);
560                    }
561                }
562                return *this;
563            }
564
565            // Dereference
566            BOOST_UBLAS_INLINE
567            const_reference operator * () const {
568                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
569                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
570                if (rank_ == 1) {
571                    return *it_;
572                } else {
573                    return (*this) () (i_, j_);
574                }
575            }
576
577#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
578            BOOST_UBLAS_INLINE
579#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
580            typename self_type::
581#endif
582            const_iterator2 begin () const {
583                const self_type &m = (*this) ();
584                return m.find2 (1, index1 (), 0);
585            }
586            BOOST_UBLAS_INLINE
587#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
588            typename self_type::
589#endif
590            const_iterator2 end () const {
591                const self_type &m = (*this) ();
592                return m.find2 (1, index1 (), m.size2 ());
593            }
594            BOOST_UBLAS_INLINE
595#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
596            typename self_type::
597#endif
598            const_reverse_iterator2 rbegin () const {
599                return const_reverse_iterator2 (end ());
600            }
601            BOOST_UBLAS_INLINE
602#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
603            typename self_type::
604#endif
605            const_reverse_iterator2 rend () const {
606                return const_reverse_iterator2 (begin ());
607            }
608#endif
609
610            // Indices
611            BOOST_UBLAS_INLINE
612            size_type index1 () const {
613                BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
614                if (rank_ == 1) {
615                    BOOST_UBLAS_CHECK (layout_type::index1 (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
616                    return layout_type::index1 (itv_.index (), it_.index ());
617                } else {
618                    return i_;
619                }
620            }
621            BOOST_UBLAS_INLINE
622            size_type index2 () const {
623                BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
624                if (rank_ == 1) {
625                    BOOST_UBLAS_CHECK (layout_type::index2 (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
626                    return layout_type::index2 (itv_.index (), it_.index ());
627                } else {
628                    return j_;
629                }
630            }
631
632            // Assignment
633            BOOST_UBLAS_INLINE
634            const_iterator1 &operator = (const const_iterator1 &it) {
635                container_const_reference<self_type>::assign (&it ());
636                rank_ = it.rank_;
637                i_ = it.i_;
638                j_ = it.j_;
639                itv_ = it.itv_;
640                it_ = it.it_;
641                return *this;
642            }
643
644            // Comparison
645            BOOST_UBLAS_INLINE
646            bool operator == (const const_iterator1 &it) const {
647                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
648                // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
649                if (rank_ == 1 || it.rank_ == 1) {
650                    return it_ == it.it_;
651                } else {
652                    return i_ == it.i_ && j_ == it.j_;
653                }
654            }
655
656        private:
657            int rank_;
658            size_type i_;
659            size_type j_;
660            const_vectoriterator_type itv_;
661            const_subiterator_type it_;
662        };
663
664        BOOST_UBLAS_INLINE
665        const_iterator1 begin1 () const {
666            return find1 (0, 0, 0);
667        }
668        BOOST_UBLAS_INLINE
669        const_iterator1 end1 () const {
670            return find1 (0, size1_, 0);
671        }
672
673        class iterator1:
674            public container_reference<generalized_vector_of_vector>,
675            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
676                                               iterator1, value_type> {
677        public:
678            typedef typename generalized_vector_of_vector::difference_type difference_type;
679            typedef typename generalized_vector_of_vector::value_type value_type;
680            typedef typename generalized_vector_of_vector::true_reference reference;
681            typedef typename generalized_vector_of_vector::pointer pointer;
682
683            typedef iterator2 dual_iterator_type;
684            typedef reverse_iterator2 dual_reverse_iterator_type;
685
686            // Construction and destruction
687            BOOST_UBLAS_INLINE
688            iterator1 ():
689                container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
690            BOOST_UBLAS_INLINE
691            iterator1 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it):
692                container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
693
694            // Arithmetic
695            BOOST_UBLAS_INLINE
696            iterator1 &operator ++ () {
697                if (rank_ == 1 && layout_type::fast1 ())
698                    ++ it_;
699                else {
700                    self_type &m = (*this) ();
701                    i_ = index1 () + 1;
702                    if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
703                        *this = m.find1 (rank_, i_, j_, 1);
704                    else if (rank_ == 1) {
705                        it_ = (*itv_).begin ();
706                        if (it_ == (*itv_).end () || index2 () != j_)
707                            *this = m.find1 (rank_, i_, j_, 1);
708                    }
709                }
710                return *this;
711            }
712            BOOST_UBLAS_INLINE
713            iterator1 &operator -- () {
714                if (rank_ == 1 && layout_type::fast1 ())
715                    -- it_;
716                else {
717                    self_type &m = (*this) ();
718                    i_ = index1 () - 1;
719                    if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
720                        *this = m.find1 (rank_, i_, j_, -1);
721                    else if (rank_ == 1) {
722                        it_ = (*itv_).begin ();
723                        if (it_ == (*itv_).end () || index2 () != j_)
724                            *this = m.find1 (rank_, i_, j_, -1);
725                    }
726                }
727                return *this;
728            }
729
730            // Dereference
731            BOOST_UBLAS_INLINE
732            true_reference operator * () const {
733                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
734                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
735                if (rank_ == 1) {
736                    return *it_;
737                } else {
738                    return (*this) ().at_element (i_, j_);
739                }
740            }
741
742#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
743            BOOST_UBLAS_INLINE
744#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
745            typename self_type::
746#endif
747            iterator2 begin () const {
748                self_type &m = (*this) ();
749                return m.find2 (1, index1 (), 0);
750            }
751            BOOST_UBLAS_INLINE
752#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
753            typename self_type::
754#endif
755            iterator2 end () const {
756                self_type &m = (*this) ();
757                return m.find2 (1, index1 (), m.size2 ());
758            }
759            BOOST_UBLAS_INLINE
760#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
761            typename self_type::
762#endif
763            reverse_iterator2 rbegin () const {
764                return reverse_iterator2 (end ());
765            }
766            BOOST_UBLAS_INLINE
767#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
768            typename self_type::
769#endif
770            reverse_iterator2 rend () const {
771                return reverse_iterator2 (begin ());
772            }
773#endif
774
775            // Indices
776            BOOST_UBLAS_INLINE
777            size_type index1 () const {
778                BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
779                if (rank_ == 1) {
780                    BOOST_UBLAS_CHECK (layout_type::index1 (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
781                    return layout_type::index1 (itv_.index (), it_.index ());
782                } else {
783                    return i_;
784                }
785            }
786            BOOST_UBLAS_INLINE
787            size_type index2 () const {
788                BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
789                if (rank_ == 1) {
790                    BOOST_UBLAS_CHECK (layout_type::index2 (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
791                    return layout_type::index2 (itv_.index (), it_.index ());
792                } else {
793                    return j_;
794                }
795            }
796
797            // Assignment
798            BOOST_UBLAS_INLINE
799            iterator1 &operator = (const iterator1 &it) {
800                container_reference<self_type>::assign (&it ());
801                rank_ = it.rank_;
802                i_ = it.i_;
803                j_ = it.j_;
804                itv_ = it.itv_;
805                it_ = it.it_;
806                return *this;
807            }
808
809            // Comparison
810            BOOST_UBLAS_INLINE
811            bool operator == (const iterator1 &it) const {
812                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
813                // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
814                if (rank_ == 1 || it.rank_ == 1) {
815                    return it_ == it.it_;
816                } else {
817                    return i_ == it.i_ && j_ == it.j_;
818                }
819            }
820
821        private:
822            int rank_;
823            size_type i_;
824            size_type j_;
825            vectoriterator_type itv_;
826            subiterator_type it_;
827           
828            friend class const_iterator1;
829        };
830
831        BOOST_UBLAS_INLINE
832        iterator1 begin1 () {
833            return find1 (0, 0, 0);
834        }
835        BOOST_UBLAS_INLINE
836        iterator1 end1 () {
837            return find1 (0, size1_, 0);
838        }
839
840        class const_iterator2:
841            public container_const_reference<generalized_vector_of_vector>,
842            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
843                                               const_iterator2, value_type> {
844        public:
845            typedef typename generalized_vector_of_vector::difference_type difference_type;
846            typedef typename generalized_vector_of_vector::value_type value_type;
847            typedef typename generalized_vector_of_vector::const_reference reference;
848            typedef const typename generalized_vector_of_vector::pointer pointer;
849
850            typedef const_iterator1 dual_iterator_type;
851            typedef const_reverse_iterator1 dual_reverse_iterator_type;
852
853            // Construction and destruction
854            BOOST_UBLAS_INLINE
855            const_iterator2 ():
856                container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
857            BOOST_UBLAS_INLINE
858            const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it):
859                container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
860            BOOST_UBLAS_INLINE
861            const_iterator2 (const iterator2 &it):
862                container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
863
864            // Arithmetic
865            BOOST_UBLAS_INLINE
866            const_iterator2 &operator ++ () {
867                if (rank_ == 1 && layout_type::fast2 ())
868                    ++ it_;
869                else {
870                    const self_type &m = (*this) ();
871                    j_ = index2 () + 1;
872                    if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
873                        *this = m.find2 (rank_, i_, j_, 1);
874                    else if (rank_ == 1) {
875                        it_ = (*itv_).begin ();
876                        if (it_ == (*itv_).end () || index1 () != i_)
877                            *this = m.find2 (rank_, i_, j_, 1);
878                    }
879                }
880                return *this;
881            }
882            BOOST_UBLAS_INLINE
883            const_iterator2 &operator -- () {
884                if (rank_ == 1 && layout_type::fast2 ())
885                    -- it_;
886                else {
887                    const self_type &m = (*this) ();
888                    j_ = index2 () - 1;
889                    if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
890                        *this = m.find2 (rank_, i_, j_, -1);
891                    else if (rank_ == 1) {
892                        it_ = (*itv_).begin ();
893                        if (it_ == (*itv_).end () || index1 () != i_)
894                            *this = m.find2 (rank_, i_, j_, -1);
895                    }
896                }
897                return *this;
898            }
899
900            // Dereference
901            BOOST_UBLAS_INLINE
902            const_reference operator * () const {
903                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
904                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
905                if (rank_ == 1) {
906                    return *it_;
907                } else {
908                    return (*this) () (i_, j_);
909                }
910            }
911
912#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
913            BOOST_UBLAS_INLINE
914#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
915            typename self_type::
916#endif
917            const_iterator1 begin () const {
918                const self_type &m = (*this) ();
919                return m.find1 (1, 0, index2 ());
920            }
921            BOOST_UBLAS_INLINE
922#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
923            typename self_type::
924#endif
925            const_iterator1 end () const {
926                const self_type &m = (*this) ();
927                return m.find1 (1, m.size1 (), index2 ());
928            }
929            BOOST_UBLAS_INLINE
930#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
931            typename self_type::
932#endif
933            const_reverse_iterator1 rbegin () const {
934                return const_reverse_iterator1 (end ());
935            }
936            BOOST_UBLAS_INLINE
937#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
938            typename self_type::
939#endif
940            const_reverse_iterator1 rend () const {
941                return const_reverse_iterator1 (begin ());
942            }
943#endif
944
945            // Indices
946            BOOST_UBLAS_INLINE
947            size_type index1 () const {
948                BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
949                if (rank_ == 1) {
950                    BOOST_UBLAS_CHECK (layout_type::index1 (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
951                    return layout_type::index1 (itv_.index (), it_.index ());
952                } else {
953                    return i_;
954                }
955            }
956            BOOST_UBLAS_INLINE
957            size_type index2 () const {
958                BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
959                if (rank_ == 1) {
960                    BOOST_UBLAS_CHECK (layout_type::index2 (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
961                    return layout_type::index2 (itv_.index (), it_.index ());
962                } else {
963                    return j_;
964                }
965            }
966
967            // Assignment
968            BOOST_UBLAS_INLINE
969            const_iterator2 &operator = (const const_iterator2 &it) {
970                container_const_reference<self_type>::assign (&it ());
971                rank_ = it.rank_;
972                i_ = it.i_;
973                j_ = it.j_;
974                itv_ = it.itv_;
975                it_ = it.it_;
976                return *this;
977            }
978
979            // Comparison
980            BOOST_UBLAS_INLINE
981            bool operator == (const const_iterator2 &it) const {
982                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
983                // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
984                if (rank_ == 1 || it.rank_ == 1) {
985                    return it_ == it.it_;
986                } else {
987                    return i_ == it.i_ && j_ == it.j_;
988                }
989            }
990
991        private:
992            int rank_;
993            size_type i_;
994            size_type j_;
995            const_vectoriterator_type itv_;
996            const_subiterator_type it_;
997        };
998
999        BOOST_UBLAS_INLINE
1000        const_iterator2 begin2 () const {
1001            return find2 (0, 0, 0);
1002        }
1003        BOOST_UBLAS_INLINE
1004        const_iterator2 end2 () const {
1005            return find2 (0, 0, size2_);
1006        }
1007
1008        class iterator2:
1009            public container_reference<generalized_vector_of_vector>,
1010            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
1011                                               iterator2, value_type> {
1012        public:
1013            typedef typename generalized_vector_of_vector::difference_type difference_type;
1014            typedef typename generalized_vector_of_vector::value_type value_type;
1015            typedef typename generalized_vector_of_vector::true_reference reference;
1016            typedef typename generalized_vector_of_vector::pointer pointer;
1017
1018            typedef iterator1 dual_iterator_type;
1019            typedef reverse_iterator1 dual_reverse_iterator_type;
1020
1021            // Construction and destruction
1022            BOOST_UBLAS_INLINE
1023            iterator2 ():
1024                container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
1025            BOOST_UBLAS_INLINE
1026            iterator2 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it):
1027                container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
1028
1029            // Arithmetic
1030            BOOST_UBLAS_INLINE
1031            iterator2 &operator ++ () {
1032                if (rank_ == 1 && layout_type::fast2 ())
1033                    ++ it_;
1034                else {
1035                    self_type &m = (*this) ();
1036                    j_ = index2 () + 1;
1037                    if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
1038                        *this = m.find2 (rank_, i_, j_, 1);
1039                    else if (rank_ == 1) {
1040                        it_ = (*itv_).begin ();
1041                        if (it_ == (*itv_).end () || index1 () != i_)
1042                            *this = m.find2 (rank_, i_, j_, 1);
1043                    }
1044                }
1045                return *this;
1046            }
1047            BOOST_UBLAS_INLINE
1048            iterator2 &operator -- () {
1049                if (rank_ == 1 && layout_type::fast2 ())
1050                    -- it_;
1051                else {
1052                    self_type &m = (*this) ();
1053                    j_ = index2 () - 1;
1054                    if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
1055                        *this = m.find2 (rank_, i_, j_, -1);
1056                    else if (rank_ == 1) {
1057                        it_ = (*itv_).begin ();
1058                        if (it_ == (*itv_).end () || index1 () != i_)
1059                            *this = m.find2 (rank_, i_, j_, -1);
1060                    }
1061                }
1062                return *this;
1063            }
1064
1065            // Dereference
1066            BOOST_UBLAS_INLINE
1067            true_reference operator * () const {
1068                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1069                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1070                if (rank_ == 1) {
1071                    return *it_;
1072                } else {
1073                    return (*this) ().at_element (i_, j_);
1074                }
1075            }
1076
1077#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1078            BOOST_UBLAS_INLINE
1079#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1080            typename self_type::
1081#endif
1082            iterator1 begin () const {
1083                self_type &m = (*this) ();
1084                return m.find1 (1, 0, index2 ());
1085            }
1086            BOOST_UBLAS_INLINE
1087#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1088            typename self_type::
1089#endif
1090            iterator1 end () const {
1091                self_type &m = (*this) ();
1092                return m.find1 (1, m.size1 (), index2 ());
1093            }
1094            BOOST_UBLAS_INLINE
1095#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1096            typename self_type::
1097#endif
1098            reverse_iterator1 rbegin () const {
1099                return reverse_iterator1 (end ());
1100            }
1101            BOOST_UBLAS_INLINE
1102#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1103            typename self_type::
1104#endif
1105            reverse_iterator1 rend () const {
1106                return reverse_iterator1 (begin ());
1107            }
1108#endif
1109
1110            // Indices
1111            BOOST_UBLAS_INLINE
1112            size_type index1 () const {
1113                BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
1114                if (rank_ == 1) {
1115                    BOOST_UBLAS_CHECK (layout_type::index1 (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
1116                    return layout_type::index1 (itv_.index (), it_.index ());
1117                } else {
1118                    return i_;
1119                }
1120            }
1121            BOOST_UBLAS_INLINE
1122            size_type index2 () const {
1123                BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
1124                if (rank_ == 1) {
1125                    BOOST_UBLAS_CHECK (layout_type::index2 (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
1126                    return layout_type::index2 (itv_.index (), it_.index ());
1127                } else {
1128                    return j_;
1129                }
1130            }
1131
1132            // Assignment
1133            BOOST_UBLAS_INLINE
1134            iterator2 &operator = (const iterator2 &it) {
1135                container_reference<self_type>::assign (&it ());
1136                rank_ = it.rank_;
1137                i_ = it.i_;
1138                j_ = it.j_;
1139                itv_ = it.itv_;
1140                it_ = it.it_;
1141                return *this;
1142            }
1143
1144            // Comparison
1145            BOOST_UBLAS_INLINE
1146            bool operator == (const iterator2 &it) const {
1147                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1148                // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
1149                if (rank_ == 1 || it.rank_ == 1) {
1150                    return it_ == it.it_;
1151                } else {
1152                    return i_ == it.i_ && j_ == it.j_;
1153                }
1154            }
1155
1156        private:
1157            int rank_;
1158            size_type i_;
1159            size_type j_;
1160            vectoriterator_type itv_;
1161            subiterator_type it_;
1162
1163            friend class const_iterator2;
1164        };
1165
1166        BOOST_UBLAS_INLINE
1167        iterator2 begin2 () {
1168            return find2 (0, 0, 0);
1169        }
1170        BOOST_UBLAS_INLINE
1171        iterator2 end2 () {
1172            return find2 (0, 0, size2_);
1173        }
1174
1175        // Reverse iterators
1176
1177        BOOST_UBLAS_INLINE
1178        const_reverse_iterator1 rbegin1 () const {
1179            return const_reverse_iterator1 (end1 ());
1180        }
1181        BOOST_UBLAS_INLINE
1182        const_reverse_iterator1 rend1 () const {
1183            return const_reverse_iterator1 (begin1 ());
1184        }
1185
1186        BOOST_UBLAS_INLINE
1187        reverse_iterator1 rbegin1 () {
1188            return reverse_iterator1 (end1 ());
1189        }
1190        BOOST_UBLAS_INLINE
1191        reverse_iterator1 rend1 () {
1192            return reverse_iterator1 (begin1 ());
1193        }
1194
1195        BOOST_UBLAS_INLINE
1196        const_reverse_iterator2 rbegin2 () const {
1197            return const_reverse_iterator2 (end2 ());
1198        }
1199        BOOST_UBLAS_INLINE
1200        const_reverse_iterator2 rend2 () const {
1201            return const_reverse_iterator2 (begin2 ());
1202        }
1203
1204        BOOST_UBLAS_INLINE
1205        reverse_iterator2 rbegin2 () {
1206            return reverse_iterator2 (end2 ());
1207        }
1208        BOOST_UBLAS_INLINE
1209        reverse_iterator2 rend2 () {
1210            return reverse_iterator2 (begin2 ());
1211        }
1212
1213    private:
1214        void storage_invariants () const
1215        {
1216            BOOST_UBLAS_CHECK (layout_type::size1 (size1_, size2_) + 1 == data_.size (), internal_logic ());
1217            BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
1218
1219        }
1220        size_type size1_;
1221        size_type size2_;
1222        array_type data_;
1223        static const value_type zero_;
1224    };
1225
1226    template<class T, class L, class A>
1227    const typename generalized_vector_of_vector<T, L, A>::value_type generalized_vector_of_vector<T, L, A>::zero_ = value_type/*zero*/();
1228
1229}}}
1230
1231#endif
Note: See TracBrowser for help on using the repository browser.