Ticket #10045: symmetric.hpp

File symmetric.hpp, 87.1 KB (added by 2015csb1032@…, 6 years ago)

Updated symmetric.hpp to support serialize function

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_SYMMETRIC_
14#define _BOOST_UBLAS_SYMMETRIC_
15
16#include <boost/numeric/ublas/matrix.hpp>
17#include <boost/numeric/ublas/triangular.hpp>
18#include <boost/numeric/ublas/detail/temporary.hpp>
19
20// Iterators based on ideas of Jeremy Siek
21// Symmetric matrices are square. Thanks to Peter Schmitteckert for spotting this.
22
23namespace boost { namespace numeric { namespace ublas {
24
25 template<class M>
26 bool is_symmetric (const M &m) {
27 typedef typename M::size_type size_type;
28
29 if (m.size1 () != m.size2 ())
30 return false;
31 size_type size = BOOST_UBLAS_SAME (m.size1 (), m.size2 ());
32 for (size_type i = 0; i < size; ++ i) {
33 for (size_type j = i; j < size; ++ j) {
34 if (m (i, j) != m (j, i))
35 return false;
36 }
37 }
38 return true;
39 }
40
41 // Array based symmetric matrix class
42 template<class T, class TRI, class L, class A>
43 class symmetric_matrix:
44 public matrix_container<symmetric_matrix<T, TRI, L, A> > {
45
46 typedef T *pointer;
47 typedef TRI triangular_type;
48 typedef L layout_type;
49 typedef symmetric_matrix<T, TRI, L, A> self_type;
50 public:
51#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
52 using matrix_container<self_type>::operator ();
53#endif
54 typedef typename A::size_type size_type;
55 typedef typename A::difference_type difference_type;
56 typedef T value_type;
57 typedef const T &const_reference;
58 typedef T &reference;
59 typedef A array_type;
60
61 typedef const matrix_reference<const self_type> const_closure_type;
62 typedef matrix_reference<self_type> closure_type;
63 typedef vector<T, A> vector_temporary_type;
64 typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix
65 typedef packed_tag storage_category;
66 typedef typename L::orientation_category orientation_category;
67
68 // Construction and destruction
69 BOOST_UBLAS_INLINE
70 symmetric_matrix ():
71 matrix_container<self_type> (),
72 size_ (0), data_ (0) {}
73 BOOST_UBLAS_INLINE
74 symmetric_matrix (size_type size):
75 matrix_container<self_type> (),
76 size_ (BOOST_UBLAS_SAME (size, size)), data_ (triangular_type::packed_size (layout_type (), size, size)) {
77 }
78 BOOST_UBLAS_INLINE
79 symmetric_matrix (size_type size1, size_type size2):
80 matrix_container<self_type> (),
81 size_ (BOOST_UBLAS_SAME (size1, size2)), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
82 }
83 BOOST_UBLAS_INLINE
84 symmetric_matrix (size_type size, const array_type &data):
85 matrix_container<self_type> (),
86 size_ (size), data_ (data) {}
87 BOOST_UBLAS_INLINE
88 symmetric_matrix (const symmetric_matrix &m):
89 matrix_container<self_type> (),
90 size_ (m.size_), data_ (m.data_) {}
91 template<class AE>
92 BOOST_UBLAS_INLINE
93 symmetric_matrix (const matrix_expression<AE> &ae):
94 matrix_container<self_type> (),
95 size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())),
96 data_ (triangular_type::packed_size (layout_type (), size_, size_)) {
97 matrix_assign<scalar_assign> (*this, ae);
98 }
99
100 // Accessors
101 BOOST_UBLAS_INLINE
102 size_type size1 () const {
103 return size_;
104 }
105 BOOST_UBLAS_INLINE
106 size_type size2 () const {
107 return size_;
108 }
109
110 // Storage accessors
111 BOOST_UBLAS_INLINE
112 const array_type &data () const {
113 return data_;
114 }
115 BOOST_UBLAS_INLINE
116 array_type &data () {
117 return data_;
118 }
119
120 // Resizing
121 BOOST_UBLAS_INLINE
122 void resize (size_type size, bool preserve = true) {
123 if (preserve) {
124 self_type temporary (size, size);
125 detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary);
126 }
127 else {
128 data ().resize (triangular_type::packed_size (layout_type (), size, size));
129 size_ = size;
130 }
131 }
132 BOOST_UBLAS_INLINE
133 void resize (size_type size1, size_type size2, bool preserve = true) {
134 resize (BOOST_UBLAS_SAME (size1, size2), preserve);
135 }
136 BOOST_UBLAS_INLINE
137 void resize_packed_preserve (size_type size) {
138 size_ = BOOST_UBLAS_SAME (size, size);
139 data ().resize (triangular_type::packed_size (layout_type (), size_, size_), value_type ());
140 }
141
142 // Element access
143 BOOST_UBLAS_INLINE
144 const_reference operator () (size_type i, size_type j) const {
145 BOOST_UBLAS_CHECK (i < size_, bad_index ());
146 BOOST_UBLAS_CHECK (j < size_, bad_index ());
147 if (triangular_type::other (i, j))
148 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
149 else
150 return data () [triangular_type::element (layout_type (), j, size_, i, size_)];
151 }
152 BOOST_UBLAS_INLINE
153 reference at_element (size_type i, size_type j) {
154 BOOST_UBLAS_CHECK (i < size_, bad_index ());
155 BOOST_UBLAS_CHECK (j < size_, bad_index ());
156 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
157 }
158 BOOST_UBLAS_INLINE
159 reference operator () (size_type i, size_type j) {
160 BOOST_UBLAS_CHECK (i < size_, bad_index ());
161 BOOST_UBLAS_CHECK (j < size_, bad_index ());
162 if (triangular_type::other (i, j))
163 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
164 else
165 return data () [triangular_type::element (layout_type (), j, size_, i, size_)];
166 }
167
168 // Element assignment
169 BOOST_UBLAS_INLINE
170 reference insert_element (size_type i, size_type j, const_reference t) {
171 return (operator () (i, j) = t);
172 }
173 BOOST_UBLAS_INLINE
174 void erase_element (size_type i, size_type j) {
175 operator () (i, j) = value_type/*zero*/();
176 }
177
178 // Zeroing
179 BOOST_UBLAS_INLINE
180 void clear () {
181 // data ().clear ();
182 std::fill (data ().begin (), data ().end (), value_type/*zero*/());
183 }
184
185 // Assignment
186 BOOST_UBLAS_INLINE
187 symmetric_matrix &operator = (const symmetric_matrix &m) {
188 size_ = m.size_;
189 data () = m.data ();
190 return *this;
191 }
192 BOOST_UBLAS_INLINE
193 symmetric_matrix &assign_temporary (symmetric_matrix &m) {
194 swap (m);
195 return *this;
196 }
197 template<class AE>
198 BOOST_UBLAS_INLINE
199 symmetric_matrix &operator = (const matrix_expression<AE> &ae) {
200 self_type temporary (ae);
201 return assign_temporary (temporary);
202 }
203 template<class AE>
204 BOOST_UBLAS_INLINE
205 symmetric_matrix &assign (const matrix_expression<AE> &ae) {
206 matrix_assign<scalar_assign> (*this, ae);
207 return *this;
208 }
209 template<class AE>
210 BOOST_UBLAS_INLINE
211 symmetric_matrix& operator += (const matrix_expression<AE> &ae) {
212 self_type temporary (*this + ae);
213 return assign_temporary (temporary);
214 }
215 template<class AE>
216 BOOST_UBLAS_INLINE
217 symmetric_matrix &plus_assign (const matrix_expression<AE> &ae) {
218 matrix_assign<scalar_plus_assign> (*this, ae);
219 return *this;
220 }
221 template<class AE>
222 BOOST_UBLAS_INLINE
223 symmetric_matrix& operator -= (const matrix_expression<AE> &ae) {
224 self_type temporary (*this - ae);
225 return assign_temporary (temporary);
226 }
227 template<class AE>
228 BOOST_UBLAS_INLINE
229 symmetric_matrix &minus_assign (const matrix_expression<AE> &ae) {
230 matrix_assign<scalar_minus_assign> (*this, ae);
231 return *this;
232 }
233 template<class AT>
234 BOOST_UBLAS_INLINE
235 symmetric_matrix& operator *= (const AT &at) {
236 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
237 return *this;
238 }
239 template<class AT>
240 BOOST_UBLAS_INLINE
241 symmetric_matrix& operator /= (const AT &at) {
242 matrix_assign_scalar<scalar_divides_assign> (*this, at);
243 return *this;
244 }
245
246 // Swapping
247 BOOST_UBLAS_INLINE
248 void swap (symmetric_matrix &m) {
249 if (this != &m) {
250 std::swap (size_, m.size_);
251 data ().swap (m.data ());
252 }
253 }
254 BOOST_UBLAS_INLINE
255 friend void swap (symmetric_matrix &m1, symmetric_matrix &m2) {
256 m1.swap (m2);
257 }
258
259 // Iterator types
260#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
261 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
262 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
263 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
264 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
265#else
266 class const_iterator1;
267 class iterator1;
268 class const_iterator2;
269 class iterator2;
270#endif
271 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
272 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
273 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
274 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
275
276 // Element lookup
277 BOOST_UBLAS_INLINE
278 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
279 return const_iterator1 (*this, i, j);
280 }
281 BOOST_UBLAS_INLINE
282 iterator1 find1 (int rank, size_type i, size_type j) {
283 if (rank == 1)
284 i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
285 if (rank == 0)
286 i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
287 return iterator1 (*this, i, j);
288 }
289 BOOST_UBLAS_INLINE
290 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
291 return const_iterator2 (*this, i, j);
292 }
293 BOOST_UBLAS_INLINE
294 iterator2 find2 (int rank, size_type i, size_type j) {
295 if (rank == 1)
296 j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
297 if (rank == 0)
298 j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
299 return iterator2 (*this, i, j);
300 }
301
302 // Iterators simply are indices.
303
304#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
305 class const_iterator1:
306 public container_const_reference<symmetric_matrix>,
307 public random_access_iterator_base<dense_random_access_iterator_tag,
308 const_iterator1, value_type> {
309 public:
310 typedef typename symmetric_matrix::value_type value_type;
311 typedef typename symmetric_matrix::difference_type difference_type;
312 typedef typename symmetric_matrix::const_reference reference;
313 typedef const typename symmetric_matrix::pointer pointer;
314
315 typedef const_iterator2 dual_iterator_type;
316 typedef const_reverse_iterator2 dual_reverse_iterator_type;
317
318 // Construction and destruction
319 BOOST_UBLAS_INLINE
320 const_iterator1 ():
321 container_const_reference<self_type> (), it1_ (), it2_ () {}
322 BOOST_UBLAS_INLINE
323 const_iterator1 (const self_type &m, size_type it1, size_type it2):
324 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
325 BOOST_UBLAS_INLINE
326 const_iterator1 (const iterator1 &it):
327 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
328
329 // Arithmetic
330 BOOST_UBLAS_INLINE
331 const_iterator1 &operator ++ () {
332 ++ it1_;
333 return *this;
334 }
335 BOOST_UBLAS_INLINE
336 const_iterator1 &operator -- () {
337 -- it1_;
338 return *this;
339 }
340 BOOST_UBLAS_INLINE
341 const_iterator1 &operator += (difference_type n) {
342 it1_ += n;
343 return *this;
344 }
345 BOOST_UBLAS_INLINE
346 const_iterator1 &operator -= (difference_type n) {
347 it1_ -= n;
348 return *this;
349 }
350 BOOST_UBLAS_INLINE
351 difference_type operator - (const const_iterator1 &it) const {
352 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
353 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
354 return it1_ - it.it1_;
355 }
356
357 // Dereference
358 BOOST_UBLAS_INLINE
359 const_reference operator * () const {
360 return (*this) () (it1_, it2_);
361 }
362 BOOST_UBLAS_INLINE
363 const_reference operator [] (difference_type n) const {
364 return *(*this + n);
365 }
366
367#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
368 BOOST_UBLAS_INLINE
369#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
370 typename self_type::
371#endif
372 const_iterator2 begin () const {
373 return (*this) ().find2 (1, it1_, 0);
374 }
375 BOOST_UBLAS_INLINE
376#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
377 typename self_type::
378#endif
379 const_iterator2 cbegin () const {
380 return begin ();
381 }
382 BOOST_UBLAS_INLINE
383#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
384 typename self_type::
385#endif
386 const_iterator2 end () const {
387 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
388 }
389 BOOST_UBLAS_INLINE
390#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
391 typename self_type::
392#endif
393 const_iterator2 cend () const {
394 return end ();
395 }
396 BOOST_UBLAS_INLINE
397#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
398 typename self_type::
399#endif
400 const_reverse_iterator2 rbegin () const {
401 return const_reverse_iterator2 (end ());
402 }
403 BOOST_UBLAS_INLINE
404#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
405 typename self_type::
406#endif
407 const_reverse_iterator2 crbegin () const {
408 return rbegin ();
409 }
410 BOOST_UBLAS_INLINE
411#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
412 typename self_type::
413#endif
414 const_reverse_iterator2 rend () const {
415 return const_reverse_iterator2 (begin ());
416 }
417 BOOST_UBLAS_INLINE
418#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
419 typename self_type::
420#endif
421 const_reverse_iterator2 crend () const {
422 return rend ();
423 }
424#endif
425
426 // Indices
427 BOOST_UBLAS_INLINE
428 size_type index1 () const {
429 return it1_;
430 }
431 BOOST_UBLAS_INLINE
432 size_type index2 () const {
433 return it2_;
434 }
435
436 // Assignment
437 BOOST_UBLAS_INLINE
438 const_iterator1 &operator = (const const_iterator1 &it) {
439 container_const_reference<self_type>::assign (&it ());
440 it1_ = it.it1_;
441 it2_ = it.it2_;
442 return *this;
443 }
444
445 // Comparison
446 BOOST_UBLAS_INLINE
447 bool operator == (const const_iterator1 &it) const {
448 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
449 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
450 return it1_ == it.it1_;
451 }
452 BOOST_UBLAS_INLINE
453 bool operator < (const const_iterator1 &it) const {
454 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
455 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
456 return it1_ < it.it1_;
457 }
458
459 private:
460 size_type it1_;
461 size_type it2_;
462 };
463#endif
464
465 BOOST_UBLAS_INLINE
466 const_iterator1 begin1 () const {
467 return find1 (0, 0, 0);
468 }
469 BOOST_UBLAS_INLINE
470 const_iterator1 cbegin1 () const {
471 return begin1 ();
472 }
473 BOOST_UBLAS_INLINE
474 const_iterator1 end1 () const {
475 return find1 (0, size_, 0);
476 }
477 BOOST_UBLAS_INLINE
478 const_iterator1 cend1 () const {
479 return end1 ();
480 }
481
482#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
483 class iterator1:
484 public container_reference<symmetric_matrix>,
485 public random_access_iterator_base<packed_random_access_iterator_tag,
486 iterator1, value_type> {
487 public:
488 typedef typename symmetric_matrix::value_type value_type;
489 typedef typename symmetric_matrix::difference_type difference_type;
490 typedef typename symmetric_matrix::reference reference;
491 typedef typename symmetric_matrix::pointer pointer;
492 typedef iterator2 dual_iterator_type;
493 typedef reverse_iterator2 dual_reverse_iterator_type;
494
495 // Construction and destruction
496 BOOST_UBLAS_INLINE
497 iterator1 ():
498 container_reference<self_type> (), it1_ (), it2_ () {}
499 BOOST_UBLAS_INLINE
500 iterator1 (self_type &m, size_type it1, size_type it2):
501 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
502
503 // Arithmetic
504 BOOST_UBLAS_INLINE
505 iterator1 &operator ++ () {
506 ++ it1_;
507 return *this;
508 }
509 BOOST_UBLAS_INLINE
510 iterator1 &operator -- () {
511 -- it1_;
512 return *this;
513 }
514 BOOST_UBLAS_INLINE
515 iterator1 &operator += (difference_type n) {
516 it1_ += n;
517 return *this;
518 }
519 BOOST_UBLAS_INLINE
520 iterator1 &operator -= (difference_type n) {
521 it1_ -= n;
522 return *this;
523 }
524 BOOST_UBLAS_INLINE
525 difference_type operator - (const iterator1 &it) const {
526 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
527 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
528 return it1_ - it.it1_;
529 }
530
531 // Dereference
532 BOOST_UBLAS_INLINE
533 reference operator * () const {
534 return (*this) () (it1_, it2_);
535 }
536 BOOST_UBLAS_INLINE
537 reference operator [] (difference_type n) const {
538 return *(*this + n);
539 }
540
541#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
542 BOOST_UBLAS_INLINE
543#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
544 typename self_type::
545#endif
546 iterator2 begin () const {
547 return (*this) ().find2 (1, it1_, 0);
548 }
549 BOOST_UBLAS_INLINE
550#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
551 typename self_type::
552#endif
553 iterator2 end () const {
554 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
555 }
556 BOOST_UBLAS_INLINE
557#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
558 typename self_type::
559#endif
560 reverse_iterator2 rbegin () const {
561 return reverse_iterator2 (end ());
562 }
563 BOOST_UBLAS_INLINE
564#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
565 typename self_type::
566#endif
567 reverse_iterator2 rend () const {
568 return reverse_iterator2 (begin ());
569 }
570#endif
571
572 // Indices
573 BOOST_UBLAS_INLINE
574 size_type index1 () const {
575 return it1_;
576 }
577 BOOST_UBLAS_INLINE
578 size_type index2 () const {
579 return it2_;
580 }
581
582 // Assignment
583 BOOST_UBLAS_INLINE
584 iterator1 &operator = (const iterator1 &it) {
585 container_reference<self_type>::assign (&it ());
586 it1_ = it.it1_;
587 it2_ = it.it2_;
588 return *this;
589 }
590
591 // Comparison
592 BOOST_UBLAS_INLINE
593 bool operator == (const iterator1 &it) const {
594 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
595 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
596 return it1_ == it.it1_;
597 }
598 BOOST_UBLAS_INLINE
599 bool operator < (const iterator1 &it) const {
600 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
601 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
602 return it1_ < it.it1_;
603 }
604
605 private:
606 size_type it1_;
607 size_type it2_;
608
609 friend class const_iterator1;
610 };
611#endif
612
613 BOOST_UBLAS_INLINE
614 iterator1 begin1 () {
615 return find1 (0, 0, 0);
616 }
617 BOOST_UBLAS_INLINE
618 iterator1 end1 () {
619 return find1 (0, size_, 0);
620 }
621
622#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
623 class const_iterator2:
624 public container_const_reference<symmetric_matrix>,
625 public random_access_iterator_base<dense_random_access_iterator_tag,
626 const_iterator2, value_type> {
627 public:
628 typedef typename symmetric_matrix::value_type value_type;
629 typedef typename symmetric_matrix::difference_type difference_type;
630 typedef typename symmetric_matrix::const_reference reference;
631 typedef const typename symmetric_matrix::pointer pointer;
632
633 typedef const_iterator1 dual_iterator_type;
634 typedef const_reverse_iterator1 dual_reverse_iterator_type;
635
636 // Construction and destruction
637 BOOST_UBLAS_INLINE
638 const_iterator2 ():
639 container_const_reference<self_type> (), it1_ (), it2_ () {}
640 BOOST_UBLAS_INLINE
641 const_iterator2 (const self_type &m, size_type it1, size_type it2):
642 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
643 BOOST_UBLAS_INLINE
644 const_iterator2 (const iterator2 &it):
645 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
646
647 // Arithmetic
648 BOOST_UBLAS_INLINE
649 const_iterator2 &operator ++ () {
650 ++ it2_;
651 return *this;
652 }
653 BOOST_UBLAS_INLINE
654 const_iterator2 &operator -- () {
655 -- it2_;
656 return *this;
657 }
658 BOOST_UBLAS_INLINE
659 const_iterator2 &operator += (difference_type n) {
660 it2_ += n;
661 return *this;
662 }
663 BOOST_UBLAS_INLINE
664 const_iterator2 &operator -= (difference_type n) {
665 it2_ -= n;
666 return *this;
667 }
668 BOOST_UBLAS_INLINE
669 difference_type operator - (const const_iterator2 &it) const {
670 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
671 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
672 return it2_ - it.it2_;
673 }
674
675 // Dereference
676 BOOST_UBLAS_INLINE
677 const_reference operator * () const {
678 return (*this) () (it1_, it2_);
679 }
680 BOOST_UBLAS_INLINE
681 const_reference operator [] (difference_type n) const {
682 return *(*this + n);
683 }
684
685#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
686 BOOST_UBLAS_INLINE
687#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
688 typename self_type::
689#endif
690 const_iterator1 begin () const {
691 return (*this) ().find1 (1, 0, it2_);
692 }
693 BOOST_UBLAS_INLINE
694#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
695 typename self_type::
696#endif
697 const_iterator1 cbegin () const {
698 return begin ();
699 }
700 BOOST_UBLAS_INLINE
701#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
702 typename self_type::
703#endif
704 const_iterator1 end () const {
705 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
706 }
707 BOOST_UBLAS_INLINE
708#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
709 typename self_type::
710#endif
711 const_iterator1 cend () const {
712 return end ();
713 }
714 BOOST_UBLAS_INLINE
715#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
716 typename self_type::
717#endif
718 const_reverse_iterator1 rbegin () const {
719 return const_reverse_iterator1 (end ());
720 }
721 BOOST_UBLAS_INLINE
722#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
723 typename self_type::
724#endif
725 const_reverse_iterator1 crbegin () const {
726 return rbegin ();
727 }
728 BOOST_UBLAS_INLINE
729#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
730 typename self_type::
731#endif
732 const_reverse_iterator1 rend () const {
733 return const_reverse_iterator1 (begin ());
734 }
735 BOOST_UBLAS_INLINE
736#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
737 typename self_type::
738#endif
739 const_reverse_iterator1 crend () const {
740 return rend ();
741 }
742#endif
743
744 // Indices
745 BOOST_UBLAS_INLINE
746 size_type index1 () const {
747 return it1_;
748 }
749 BOOST_UBLAS_INLINE
750 size_type index2 () const {
751 return it2_;
752 }
753
754 // Assignment
755 BOOST_UBLAS_INLINE
756 const_iterator2 &operator = (const const_iterator2 &it) {
757 container_const_reference<self_type>::assign (&it ());
758 it1_ = it.it1_;
759 it2_ = it.it2_;
760 return *this;
761 }
762
763 // Comparison
764 BOOST_UBLAS_INLINE
765 bool operator == (const const_iterator2 &it) const {
766 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
767 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
768 return it2_ == it.it2_;
769 }
770 BOOST_UBLAS_INLINE
771 bool operator < (const const_iterator2 &it) const {
772 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
773 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
774 return it2_ < it.it2_;
775 }
776
777 private:
778 size_type it1_;
779 size_type it2_;
780 };
781#endif
782
783 BOOST_UBLAS_INLINE
784 const_iterator2 begin2 () const {
785 return find2 (0, 0, 0);
786 }
787 BOOST_UBLAS_INLINE
788 const_iterator2 cbegin2 () const {
789 return begin2 ();
790 }
791 BOOST_UBLAS_INLINE
792 const_iterator2 end2 () const {
793 return find2 (0, 0, size_);
794 }
795 BOOST_UBLAS_INLINE
796 const_iterator2 cend2 () const {
797 return end2 ();
798 }
799
800#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
801 class iterator2:
802 public container_reference<symmetric_matrix>,
803 public random_access_iterator_base<packed_random_access_iterator_tag,
804 iterator2, value_type> {
805 public:
806 typedef typename symmetric_matrix::value_type value_type;
807 typedef typename symmetric_matrix::difference_type difference_type;
808 typedef typename symmetric_matrix::reference reference;
809 typedef typename symmetric_matrix::pointer pointer;
810
811 typedef iterator1 dual_iterator_type;
812 typedef reverse_iterator1 dual_reverse_iterator_type;
813
814 // Construction and destruction
815 BOOST_UBLAS_INLINE
816 iterator2 ():
817 container_reference<self_type> (), it1_ (), it2_ () {}
818 BOOST_UBLAS_INLINE
819 iterator2 (self_type &m, size_type it1, size_type it2):
820 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
821
822 // Arithmetic
823 BOOST_UBLAS_INLINE
824 iterator2 &operator ++ () {
825 ++ it2_;
826 return *this;
827 }
828 BOOST_UBLAS_INLINE
829 iterator2 &operator -- () {
830 -- it2_;
831 return *this;
832 }
833 BOOST_UBLAS_INLINE
834 iterator2 &operator += (difference_type n) {
835 it2_ += n;
836 return *this;
837 }
838 BOOST_UBLAS_INLINE
839 iterator2 &operator -= (difference_type n) {
840 it2_ -= n;
841 return *this;
842 }
843 BOOST_UBLAS_INLINE
844 difference_type operator - (const iterator2 &it) const {
845 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
846 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
847 return it2_ - it.it2_;
848 }
849
850 // Dereference
851 BOOST_UBLAS_INLINE
852 reference operator * () const {
853 return (*this) () (it1_, it2_);
854 }
855 BOOST_UBLAS_INLINE
856 reference operator [] (difference_type n) const {
857 return *(*this + n);
858 }
859
860#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
861 BOOST_UBLAS_INLINE
862#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
863 typename self_type::
864#endif
865 iterator1 begin () const {
866 return (*this) ().find1 (1, 0, it2_);
867 }
868 BOOST_UBLAS_INLINE
869#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
870 typename self_type::
871#endif
872 iterator1 end () const {
873 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
874 }
875 BOOST_UBLAS_INLINE
876#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
877 typename self_type::
878#endif
879 reverse_iterator1 rbegin () const {
880 return reverse_iterator1 (end ());
881 }
882 BOOST_UBLAS_INLINE
883#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
884 typename self_type::
885#endif
886 reverse_iterator1 rend () const {
887 return reverse_iterator1 (begin ());
888 }
889#endif
890
891 // Indices
892 BOOST_UBLAS_INLINE
893 size_type index1 () const {
894 return it1_;
895 }
896 BOOST_UBLAS_INLINE
897 size_type index2 () const {
898 return it2_;
899 }
900
901 // Assignment
902 BOOST_UBLAS_INLINE
903 iterator2 &operator = (const iterator2 &it) {
904 container_reference<self_type>::assign (&it ());
905 it1_ = it.it1_;
906 it2_ = it.it2_;
907 return *this;
908 }
909
910 // Comparison
911 BOOST_UBLAS_INLINE
912 bool operator == (const iterator2 &it) const {
913 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
914 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
915 return it2_ == it.it2_;
916 }
917 BOOST_UBLAS_INLINE
918 bool operator < (const iterator2 &it) const {
919 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
920 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
921 return it2_ < it.it2_;
922 }
923
924 private:
925 size_type it1_;
926 size_type it2_;
927
928 friend class const_iterator2;
929 };
930#endif
931
932 BOOST_UBLAS_INLINE
933 iterator2 begin2 () {
934 return find2 (0, 0, 0);
935 }
936 BOOST_UBLAS_INLINE
937 iterator2 end2 () {
938 return find2 (0, 0, size_);
939 }
940
941 // Reverse iterators
942
943 BOOST_UBLAS_INLINE
944 const_reverse_iterator1 rbegin1 () const {
945 return const_reverse_iterator1 (end1 ());
946 }
947 BOOST_UBLAS_INLINE
948 const_reverse_iterator1 crbegin1 () const {
949 return rbegin1 ();
950 }
951 BOOST_UBLAS_INLINE
952 const_reverse_iterator1 rend1 () const {
953 return const_reverse_iterator1 (begin1 ());
954 }
955 BOOST_UBLAS_INLINE
956 const_reverse_iterator1 crend1 () const {
957 return rend1 ();
958 }
959
960 BOOST_UBLAS_INLINE
961 reverse_iterator1 rbegin1 () {
962 return reverse_iterator1 (end1 ());
963 }
964 BOOST_UBLAS_INLINE
965 reverse_iterator1 rend1 () {
966 return reverse_iterator1 (begin1 ());
967 }
968
969 BOOST_UBLAS_INLINE
970 const_reverse_iterator2 rbegin2 () const {
971 return const_reverse_iterator2 (end2 ());
972 }
973 BOOST_UBLAS_INLINE
974 const_reverse_iterator2 crbegin2 () const {
975 return rbegin2 ();
976 }
977 BOOST_UBLAS_INLINE
978 const_reverse_iterator2 rend2 () const {
979 return const_reverse_iterator2 (begin2 ());
980 }
981 BOOST_UBLAS_INLINE
982 const_reverse_iterator2 crend2 () const {
983 return rend2 ();
984 }
985 BOOST_UBLAS_INLINE
986 reverse_iterator2 rbegin2 () {
987 return reverse_iterator2 (end2 ());
988 }
989 BOOST_UBLAS_INLINE
990 reverse_iterator2 rend2 () {
991 return reverse_iterator2 (begin2 ());
992 }
993
994 // Serialization
995 template<class Archive>
996 void serialize(Archive & ar, const unsigned int ){
997
998 serialization::collection_size_type s1 (size_);
999 serialization::collection_size_type s2 (size_);
1000
1001 ar & serialization::make_nvp("size1",s1)
1002 & serialization::make_nvp("size2",s2);
1003
1004 if (Archive::is_loading::value) {
1005 size_ = s1;
1006 }
1007 ar & serialization::make_nvp("data",data_);
1008 }
1009
1010 private:
1011 size_type size_;
1012 array_type data_;
1013 };
1014
1015
1016 // Symmetric matrix adaptor class
1017 template<class M, class TRI>
1018 class symmetric_adaptor:
1019 public matrix_expression<symmetric_adaptor<M, TRI> > {
1020
1021 typedef symmetric_adaptor<M, TRI> self_type;
1022 public:
1023#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1024 using matrix_expression<self_type>::operator ();
1025#endif
1026 typedef const M const_matrix_type;
1027 typedef M matrix_type;
1028 typedef TRI triangular_type;
1029 typedef typename M::size_type size_type;
1030 typedef typename M::difference_type difference_type;
1031 typedef typename M::value_type value_type;
1032 typedef typename M::const_reference const_reference;
1033 typedef typename boost::mpl::if_<boost::is_const<M>,
1034 typename M::const_reference,
1035 typename M::reference>::type reference;
1036 typedef typename boost::mpl::if_<boost::is_const<M>,
1037 typename M::const_closure_type,
1038 typename M::closure_type>::type matrix_closure_type;
1039 typedef const self_type const_closure_type;
1040 typedef self_type closure_type;
1041 // Replaced by _temporary_traits to avoid type requirements on M
1042 //typedef typename M::vector_temporary_type vector_temporary_type;
1043 //typedef typename M::matrix_temporary_type matrix_temporary_type;
1044 typedef typename storage_restrict_traits<typename M::storage_category,
1045 packed_proxy_tag>::storage_category storage_category;
1046 typedef typename M::orientation_category orientation_category;
1047
1048 // Construction and destruction
1049 BOOST_UBLAS_INLINE
1050 symmetric_adaptor (matrix_type &data):
1051 matrix_expression<self_type> (),
1052 data_ (data) {
1053 BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
1054 }
1055 BOOST_UBLAS_INLINE
1056 symmetric_adaptor (const symmetric_adaptor &m):
1057 matrix_expression<self_type> (),
1058 data_ (m.data_) {
1059 BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
1060 }
1061
1062 // Accessors
1063 BOOST_UBLAS_INLINE
1064 size_type size1 () const {
1065 return data_.size1 ();
1066 }
1067 BOOST_UBLAS_INLINE
1068 size_type size2 () const {
1069 return data_.size2 ();
1070 }
1071
1072 // Storage accessors
1073 BOOST_UBLAS_INLINE
1074 const matrix_closure_type &data () const {
1075 return data_;
1076 }
1077 BOOST_UBLAS_INLINE
1078 matrix_closure_type &data () {
1079 return data_;
1080 }
1081
1082 // Element access
1083#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1084 BOOST_UBLAS_INLINE
1085 const_reference operator () (size_type i, size_type j) const {
1086 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1087 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1088 if (triangular_type::other (i, j))
1089 return data () (i, j);
1090 else
1091 return data () (j, i);
1092 }
1093 BOOST_UBLAS_INLINE
1094 reference operator () (size_type i, size_type j) {
1095 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1096 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1097 if (triangular_type::other (i, j))
1098 return data () (i, j);
1099 else
1100 return data () (j, i);
1101 }
1102#else
1103 BOOST_UBLAS_INLINE
1104 reference operator () (size_type i, size_type j) const {
1105 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1106 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1107 if (triangular_type::other (i, j))
1108 return data () (i, j);
1109 else
1110 return data () (j, i);
1111 }
1112#endif
1113
1114 // Assignment
1115 BOOST_UBLAS_INLINE
1116 symmetric_adaptor &operator = (const symmetric_adaptor &m) {
1117 matrix_assign<scalar_assign, triangular_type> (*this, m);
1118 return *this;
1119 }
1120 BOOST_UBLAS_INLINE
1121 symmetric_adaptor &assign_temporary (symmetric_adaptor &m) {
1122 *this = m;
1123 return *this;
1124 }
1125 template<class AE>
1126 BOOST_UBLAS_INLINE
1127 symmetric_adaptor &operator = (const matrix_expression<AE> &ae) {
1128 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae));
1129 return *this;
1130 }
1131 template<class AE>
1132 BOOST_UBLAS_INLINE
1133 symmetric_adaptor &assign (const matrix_expression<AE> &ae) {
1134 matrix_assign<scalar_assign, triangular_type> (*this, ae);
1135 return *this;
1136 }
1137 template<class AE>
1138 BOOST_UBLAS_INLINE
1139 symmetric_adaptor& operator += (const matrix_expression<AE> &ae) {
1140 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae));
1141 return *this;
1142 }
1143 template<class AE>
1144 BOOST_UBLAS_INLINE
1145 symmetric_adaptor &plus_assign (const matrix_expression<AE> &ae) {
1146 matrix_assign<scalar_plus_assign, triangular_type> (*this, ae);
1147 return *this;
1148 }
1149 template<class AE>
1150 BOOST_UBLAS_INLINE
1151 symmetric_adaptor& operator -= (const matrix_expression<AE> &ae) {
1152 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae));
1153 return *this;
1154 }
1155 template<class AE>
1156 BOOST_UBLAS_INLINE
1157 symmetric_adaptor &minus_assign (const matrix_expression<AE> &ae) {
1158 matrix_assign<scalar_minus_assign, triangular_type> (*this, ae);
1159 return *this;
1160 }
1161 template<class AT>
1162 BOOST_UBLAS_INLINE
1163 symmetric_adaptor& operator *= (const AT &at) {
1164 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
1165 return *this;
1166 }
1167 template<class AT>
1168 BOOST_UBLAS_INLINE
1169 symmetric_adaptor& operator /= (const AT &at) {
1170 matrix_assign_scalar<scalar_divides_assign> (*this, at);
1171 return *this;
1172 }
1173
1174 // Closure comparison
1175 BOOST_UBLAS_INLINE
1176 bool same_closure (const symmetric_adaptor &sa) const {
1177 return (*this).data ().same_closure (sa.data ());
1178 }
1179
1180 // Swapping
1181 BOOST_UBLAS_INLINE
1182 void swap (symmetric_adaptor &m) {
1183 if (this != &m)
1184 matrix_swap<scalar_swap, triangular_type> (*this, m);
1185 }
1186 BOOST_UBLAS_INLINE
1187 friend void swap (symmetric_adaptor &m1, symmetric_adaptor &m2) {
1188 m1.swap (m2);
1189 }
1190
1191 // Iterator types
1192 private:
1193 // Use matrix iterator
1194 typedef typename M::const_iterator1 const_subiterator1_type;
1195 typedef typename boost::mpl::if_<boost::is_const<M>,
1196 typename M::const_iterator1,
1197 typename M::iterator1>::type subiterator1_type;
1198 typedef typename M::const_iterator2 const_subiterator2_type;
1199 typedef typename boost::mpl::if_<boost::is_const<M>,
1200 typename M::const_iterator2,
1201 typename M::iterator2>::type subiterator2_type;
1202
1203 public:
1204#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1205 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
1206 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
1207 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
1208 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
1209#else
1210 class const_iterator1;
1211 class iterator1;
1212 class const_iterator2;
1213 class iterator2;
1214#endif
1215 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1216 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
1217 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1218 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
1219
1220 // Element lookup
1221 BOOST_UBLAS_INLINE
1222 const_iterator1 find1 (int rank, size_type i, size_type j) const {
1223 if (triangular_type::other (i, j)) {
1224 if (triangular_type::other (size1 (), j)) {
1225 return const_iterator1 (*this, 0, 0,
1226 data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j),
1227 data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ()));
1228 } else {
1229 return const_iterator1 (*this, 0, 1,
1230 data ().find1 (rank, i, j), data ().find1 (rank, j, j),
1231 data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ()));
1232 }
1233 } else {
1234 if (triangular_type::other (size1 (), j)) {
1235 return const_iterator1 (*this, 1, 0,
1236 data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j),
1237 data ().find2 (rank, j, i), data ().find2 (rank, j, j));
1238 } else {
1239 return const_iterator1 (*this, 1, 1,
1240 data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()),
1241 data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ()));
1242 }
1243 }
1244 }
1245 BOOST_UBLAS_INLINE
1246 iterator1 find1 (int rank, size_type i, size_type j) {
1247 if (rank == 1)
1248 i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
1249 return iterator1 (*this, data ().find1 (rank, i, j));
1250 }
1251 BOOST_UBLAS_INLINE
1252 const_iterator2 find2 (int rank, size_type i, size_type j) const {
1253 if (triangular_type::other (i, j)) {
1254 if (triangular_type::other (i, size2 ())) {
1255 return const_iterator2 (*this, 1, 1,
1256 data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()),
1257 data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ()));
1258 } else {
1259 return const_iterator2 (*this, 1, 0,
1260 data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i),
1261 data ().find2 (rank, i, j), data ().find2 (rank, i, i));
1262 }
1263 } else {
1264 if (triangular_type::other (i, size2 ())) {
1265 return const_iterator2 (*this, 0, 1,
1266 data ().find1 (rank, j, i), data ().find1 (rank, i, i),
1267 data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ()));
1268 } else {
1269 return const_iterator2 (*this, 0, 0,
1270 data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i),
1271 data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ()));
1272 }
1273 }
1274 }
1275 BOOST_UBLAS_INLINE
1276 iterator2 find2 (int rank, size_type i, size_type j) {
1277 if (rank == 1)
1278 j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
1279 return iterator2 (*this, data ().find2 (rank, i, j));
1280 }
1281
1282 // Iterators simply are indices.
1283
1284#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1285 class const_iterator1:
1286 public container_const_reference<symmetric_adaptor>,
1287 public random_access_iterator_base<typename iterator_restrict_traits<
1288 typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
1289 const_iterator1, value_type> {
1290 public:
1291 typedef typename const_subiterator1_type::value_type value_type;
1292 typedef typename const_subiterator1_type::difference_type difference_type;
1293 typedef typename const_subiterator1_type::reference reference;
1294 typedef typename const_subiterator1_type::pointer pointer;
1295
1296 typedef const_iterator2 dual_iterator_type;
1297 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1298
1299 // Construction and destruction
1300 BOOST_UBLAS_INLINE
1301 const_iterator1 ():
1302 container_const_reference<self_type> (),
1303 begin_ (-1), end_ (-1), current_ (-1),
1304 it1_begin_ (), it1_end_ (), it1_ (),
1305 it2_begin_ (), it2_end_ (), it2_ () {}
1306 BOOST_UBLAS_INLINE
1307 const_iterator1 (const self_type &m, int begin, int end,
1308 const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
1309 const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
1310 container_const_reference<self_type> (m),
1311 begin_ (begin), end_ (end), current_ (begin),
1312 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
1313 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
1314 if (current_ == 0 && it1_ == it1_end_)
1315 current_ = 1;
1316 if (current_ == 1 && it2_ == it2_end_)
1317 current_ = 0;
1318 if ((current_ == 0 && it1_ == it1_end_) ||
1319 (current_ == 1 && it2_ == it2_end_))
1320 current_ = end_;
1321 BOOST_UBLAS_CHECK (current_ == end_ ||
1322 (current_ == 0 && it1_ != it1_end_) ||
1323 (current_ == 1 && it2_ != it2_end_), internal_logic ());
1324 }
1325 // FIXME cannot compile
1326 // iterator1 does not have these members!
1327 BOOST_UBLAS_INLINE
1328 const_iterator1 (const iterator1 &it):
1329 container_const_reference<self_type> (it ()),
1330 begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
1331 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
1332 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
1333 BOOST_UBLAS_CHECK (current_ == end_ ||
1334 (current_ == 0 && it1_ != it1_end_) ||
1335 (current_ == 1 && it2_ != it2_end_), internal_logic ());
1336 }
1337
1338 // Arithmetic
1339 BOOST_UBLAS_INLINE
1340 const_iterator1 &operator ++ () {
1341 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1342 if (current_ == 0) {
1343 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1344 ++ it1_;
1345 if (it1_ == it1_end_ && end_ == 1) {
1346 it2_ = it2_begin_;
1347 current_ = 1;
1348 }
1349 } else /* if (current_ == 1) */ {
1350 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1351 ++ it2_;
1352 if (it2_ == it2_end_ && end_ == 0) {
1353 it1_ = it1_begin_;
1354 current_ = 0;
1355 }
1356 }
1357 return *this;
1358 }
1359 BOOST_UBLAS_INLINE
1360 const_iterator1 &operator -- () {
1361 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1362 if (current_ == 0) {
1363 if (it1_ == it1_begin_ && begin_ == 1) {
1364 it2_ = it2_end_;
1365 BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
1366 -- it2_;
1367 current_ = 1;
1368 } else {
1369 -- it1_;
1370 }
1371 } else /* if (current_ == 1) */ {
1372 if (it2_ == it2_begin_ && begin_ == 0) {
1373 it1_ = it1_end_;
1374 BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
1375 -- it1_;
1376 current_ = 0;
1377 } else {
1378 -- it2_;
1379 }
1380 }
1381 return *this;
1382 }
1383 BOOST_UBLAS_INLINE
1384 const_iterator1 &operator += (difference_type n) {
1385 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1386 if (current_ == 0) {
1387 size_type d = (std::min) (n, it1_end_ - it1_);
1388 it1_ += d;
1389 n -= d;
1390 if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
1391 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1392 d = (std::min) (n, it2_end_ - it2_begin_);
1393 it2_ = it2_begin_ + d;
1394 n -= d;
1395 current_ = 1;
1396 }
1397 } else /* if (current_ == 1) */ {
1398 size_type d = (std::min) (n, it2_end_ - it2_);
1399 it2_ += d;
1400 n -= d;
1401 if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
1402 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1403 d = (std::min) (n, it1_end_ - it1_begin_);
1404 it1_ = it1_begin_ + d;
1405 n -= d;
1406 current_ = 0;
1407 }
1408 }
1409 BOOST_UBLAS_CHECK (n == 0, external_logic ());
1410 return *this;
1411 }
1412 BOOST_UBLAS_INLINE
1413 const_iterator1 &operator -= (difference_type n) {
1414 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1415 if (current_ == 0) {
1416 size_type d = (std::min) (n, it1_ - it1_begin_);
1417 it1_ -= d;
1418 n -= d;
1419 if (n > 0) {
1420 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1421 d = (std::min) (n, it2_end_ - it2_begin_);
1422 it2_ = it2_end_ - d;
1423 n -= d;
1424 current_ = 1;
1425 }
1426 } else /* if (current_ == 1) */ {
1427 size_type d = (std::min) (n, it2_ - it2_begin_);
1428 it2_ -= d;
1429 n -= d;
1430 if (n > 0) {
1431 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1432 d = (std::min) (n, it1_end_ - it1_begin_);
1433 it1_ = it1_end_ - d;
1434 n -= d;
1435 current_ = 0;
1436 }
1437 }
1438 BOOST_UBLAS_CHECK (n == 0, external_logic ());
1439 return *this;
1440 }
1441 BOOST_UBLAS_INLINE
1442 difference_type operator - (const const_iterator1 &it) const {
1443 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1444 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1445 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1446 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1447 if (current_ == 0 && it.current_ == 0) {
1448 return it1_ - it.it1_;
1449 } else if (current_ == 0 && it.current_ == 1) {
1450 if (end_ == 1 && it.end_ == 1) {
1451 return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
1452 } else /* if (end_ == 0 && it.end_ == 0) */ {
1453 return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
1454 }
1455
1456 } else if (current_ == 1 && it.current_ == 0) {
1457 if (end_ == 1 && it.end_ == 1) {
1458 return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
1459 } else /* if (end_ == 0 && it.end_ == 0) */ {
1460 return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
1461 }
1462 }
1463 /* current_ == 1 && it.current_ == 1 */ {
1464 return it2_ - it.it2_;
1465 }
1466 }
1467
1468 // Dereference
1469 BOOST_UBLAS_INLINE
1470 const_reference operator * () const {
1471 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1472 if (current_ == 0) {
1473 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1474 return *it1_;
1475 } else /* if (current_ == 1) */ {
1476 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1477 return *it2_;
1478 }
1479 }
1480 BOOST_UBLAS_INLINE
1481 const_reference operator [] (difference_type n) const {
1482 return *(*this + n);
1483 }
1484
1485#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1486 BOOST_UBLAS_INLINE
1487#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1488 typename self_type::
1489#endif
1490 const_iterator2 begin () const {
1491 return (*this) ().find2 (1, index1 (), 0);
1492 }
1493 BOOST_UBLAS_INLINE
1494#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1495 typename self_type::
1496#endif
1497 const_iterator2 cbegin () const {
1498 return begin ();
1499 }
1500 BOOST_UBLAS_INLINE
1501#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1502 typename self_type::
1503#endif
1504 const_iterator2 end () const {
1505 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1506 }
1507 BOOST_UBLAS_INLINE
1508#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1509 typename self_type::
1510#endif
1511 const_iterator2 cend () const {
1512 return end ();
1513 }
1514 BOOST_UBLAS_INLINE
1515#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1516 typename self_type::
1517#endif
1518 const_reverse_iterator2 rbegin () const {
1519 return const_reverse_iterator2 (end ());
1520 }
1521 BOOST_UBLAS_INLINE
1522#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1523 typename self_type::
1524#endif
1525 const_reverse_iterator2 crbegin () const {
1526 return rbegin ();
1527 }
1528 BOOST_UBLAS_INLINE
1529#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1530 typename self_type::
1531#endif
1532 const_reverse_iterator2 rend () const {
1533 return const_reverse_iterator2 (begin ());
1534 }
1535 BOOST_UBLAS_INLINE
1536#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1537 typename self_type::
1538#endif
1539 const_reverse_iterator2 crend () const {
1540 return rend ();
1541 }
1542#endif
1543
1544 // Indices
1545 BOOST_UBLAS_INLINE
1546 size_type index1 () const {
1547 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1548 if (current_ == 0) {
1549 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1550 return it1_.index1 ();
1551 } else /* if (current_ == 1) */ {
1552 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1553 return it2_.index2 ();
1554 }
1555 }
1556 BOOST_UBLAS_INLINE
1557 size_type index2 () const {
1558 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1559 if (current_ == 0) {
1560 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1561 return it1_.index2 ();
1562 } else /* if (current_ == 1) */ {
1563 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1564 return it2_.index1 ();
1565 }
1566 }
1567
1568 // Assignment
1569 BOOST_UBLAS_INLINE
1570 const_iterator1 &operator = (const const_iterator1 &it) {
1571 container_const_reference<self_type>::assign (&it ());
1572 begin_ = it.begin_;
1573 end_ = it.end_;
1574 current_ = it.current_;
1575 it1_begin_ = it.it1_begin_;
1576 it1_end_ = it.it1_end_;
1577 it1_ = it.it1_;
1578 it2_begin_ = it.it2_begin_;
1579 it2_end_ = it.it2_end_;
1580 it2_ = it.it2_;
1581 return *this;
1582 }
1583
1584 // Comparison
1585 BOOST_UBLAS_INLINE
1586 bool operator == (const const_iterator1 &it) const {
1587 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1588 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1589 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1590 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1591 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
1592 (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
1593 }
1594 BOOST_UBLAS_INLINE
1595 bool operator < (const const_iterator1 &it) const {
1596 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1597 return it - *this > 0;
1598 }
1599
1600 private:
1601 int begin_;
1602 int end_;
1603 int current_;
1604 const_subiterator1_type it1_begin_;
1605 const_subiterator1_type it1_end_;
1606 const_subiterator1_type it1_;
1607 const_subiterator2_type it2_begin_;
1608 const_subiterator2_type it2_end_;
1609 const_subiterator2_type it2_;
1610 };
1611#endif
1612
1613 BOOST_UBLAS_INLINE
1614 const_iterator1 begin1 () const {
1615 return find1 (0, 0, 0);
1616 }
1617 BOOST_UBLAS_INLINE
1618 const_iterator1 cbegin1 () const {
1619 return begin1 ();
1620 }
1621 BOOST_UBLAS_INLINE
1622 const_iterator1 end1 () const {
1623 return find1 (0, size1 (), 0);
1624 }
1625 BOOST_UBLAS_INLINE
1626 const_iterator1 cend1 () const {
1627 return end1 ();
1628 }
1629
1630#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1631 class iterator1:
1632 public container_reference<symmetric_adaptor>,
1633 public random_access_iterator_base<typename iterator_restrict_traits<
1634 typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1635 iterator1, value_type> {
1636 public:
1637 typedef typename subiterator1_type::value_type value_type;
1638 typedef typename subiterator1_type::difference_type difference_type;
1639 typedef typename subiterator1_type::reference reference;
1640 typedef typename subiterator1_type::pointer pointer;
1641
1642 typedef iterator2 dual_iterator_type;
1643 typedef reverse_iterator2 dual_reverse_iterator_type;
1644
1645 // Construction and destruction
1646 BOOST_UBLAS_INLINE
1647 iterator1 ():
1648 container_reference<self_type> (), it1_ () {}
1649 BOOST_UBLAS_INLINE
1650 iterator1 (self_type &m, const subiterator1_type &it1):
1651 container_reference<self_type> (m), it1_ (it1) {}
1652
1653 // Arithmetic
1654 BOOST_UBLAS_INLINE
1655 iterator1 &operator ++ () {
1656 ++ it1_;
1657 return *this;
1658 }
1659 BOOST_UBLAS_INLINE
1660 iterator1 &operator -- () {
1661 -- it1_;
1662 return *this;
1663 }
1664 BOOST_UBLAS_INLINE
1665 iterator1 &operator += (difference_type n) {
1666 it1_ += n;
1667 return *this;
1668 }
1669 BOOST_UBLAS_INLINE
1670 iterator1 &operator -= (difference_type n) {
1671 it1_ -= n;
1672 return *this;
1673 }
1674 BOOST_UBLAS_INLINE
1675 difference_type operator - (const iterator1 &it) const {
1676 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1677 return it1_ - it.it1_;
1678 }
1679
1680 // Dereference
1681 BOOST_UBLAS_INLINE
1682 reference operator * () const {
1683 return *it1_;
1684 }
1685 BOOST_UBLAS_INLINE
1686 reference operator [] (difference_type n) const {
1687 return *(*this + n);
1688 }
1689
1690#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1691 BOOST_UBLAS_INLINE
1692#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1693 typename self_type::
1694#endif
1695 iterator2 begin () const {
1696 return (*this) ().find2 (1, index1 (), 0);
1697 }
1698 BOOST_UBLAS_INLINE
1699#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1700 typename self_type::
1701#endif
1702 iterator2 end () const {
1703 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1704 }
1705 BOOST_UBLAS_INLINE
1706#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1707 typename self_type::
1708#endif
1709 reverse_iterator2 rbegin () const {
1710 return reverse_iterator2 (end ());
1711 }
1712 BOOST_UBLAS_INLINE
1713#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1714 typename self_type::
1715#endif
1716 reverse_iterator2 rend () const {
1717 return reverse_iterator2 (begin ());
1718 }
1719#endif
1720
1721 // Indices
1722 BOOST_UBLAS_INLINE
1723 size_type index1 () const {
1724 return it1_.index1 ();
1725 }
1726 BOOST_UBLAS_INLINE
1727 size_type index2 () const {
1728 return it1_.index2 ();
1729 }
1730
1731 // Assignment
1732 BOOST_UBLAS_INLINE
1733 iterator1 &operator = (const iterator1 &it) {
1734 container_reference<self_type>::assign (&it ());
1735 it1_ = it.it1_;
1736 return *this;
1737 }
1738
1739 // Comparison
1740 BOOST_UBLAS_INLINE
1741 bool operator == (const iterator1 &it) const {
1742 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1743 return it1_ == it.it1_;
1744 }
1745 BOOST_UBLAS_INLINE
1746 bool operator < (const iterator1 &it) const {
1747 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1748 return it1_ < it.it1_;
1749 }
1750
1751 private:
1752 subiterator1_type it1_;
1753
1754 friend class const_iterator1;
1755 };
1756#endif
1757
1758 BOOST_UBLAS_INLINE
1759 iterator1 begin1 () {
1760 return find1 (0, 0, 0);
1761 }
1762 BOOST_UBLAS_INLINE
1763 iterator1 end1 () {
1764 return find1 (0, size1 (), 0);
1765 }
1766
1767#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1768 class const_iterator2:
1769 public container_const_reference<symmetric_adaptor>,
1770 public random_access_iterator_base<typename iterator_restrict_traits<
1771 typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
1772 const_iterator2, value_type> {
1773 public:
1774 typedef typename const_subiterator2_type::value_type value_type;
1775 typedef typename const_subiterator2_type::difference_type difference_type;
1776 typedef typename const_subiterator2_type::reference reference;
1777 typedef typename const_subiterator2_type::pointer pointer;
1778
1779 typedef const_iterator1 dual_iterator_type;
1780 typedef const_reverse_iterator1 dual_reverse_iterator_type;
1781
1782 // Construction and destruction
1783 BOOST_UBLAS_INLINE
1784 const_iterator2 ():
1785 container_const_reference<self_type> (),
1786 begin_ (-1), end_ (-1), current_ (-1),
1787 it1_begin_ (), it1_end_ (), it1_ (),
1788 it2_begin_ (), it2_end_ (), it2_ () {}
1789 BOOST_UBLAS_INLINE
1790 const_iterator2 (const self_type &m, int begin, int end,
1791 const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
1792 const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
1793 container_const_reference<self_type> (m),
1794 begin_ (begin), end_ (end), current_ (begin),
1795 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
1796 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
1797 if (current_ == 0 && it1_ == it1_end_)
1798 current_ = 1;
1799 if (current_ == 1 && it2_ == it2_end_)
1800 current_ = 0;
1801 if ((current_ == 0 && it1_ == it1_end_) ||
1802 (current_ == 1 && it2_ == it2_end_))
1803 current_ = end_;
1804 BOOST_UBLAS_CHECK (current_ == end_ ||
1805 (current_ == 0 && it1_ != it1_end_) ||
1806 (current_ == 1 && it2_ != it2_end_), internal_logic ());
1807 }
1808 // FIXME cannot compiler
1809 // iterator2 does not have these members!
1810 BOOST_UBLAS_INLINE
1811 const_iterator2 (const iterator2 &it):
1812 container_const_reference<self_type> (it ()),
1813 begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
1814 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
1815 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
1816 BOOST_UBLAS_CHECK (current_ == end_ ||
1817 (current_ == 0 && it1_ != it1_end_) ||
1818 (current_ == 1 && it2_ != it2_end_), internal_logic ());
1819 }
1820
1821 // Arithmetic
1822 BOOST_UBLAS_INLINE
1823 const_iterator2 &operator ++ () {
1824 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1825 if (current_ == 0) {
1826 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1827 ++ it1_;
1828 if (it1_ == it1_end_ && end_ == 1) {
1829 it2_ = it2_begin_;
1830 current_ = 1;
1831 }
1832 } else /* if (current_ == 1) */ {
1833 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1834 ++ it2_;
1835 if (it2_ == it2_end_ && end_ == 0) {
1836 it1_ = it1_begin_;
1837 current_ = 0;
1838 }
1839 }
1840 return *this;
1841 }
1842 BOOST_UBLAS_INLINE
1843 const_iterator2 &operator -- () {
1844 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1845 if (current_ == 0) {
1846 if (it1_ == it1_begin_ && begin_ == 1) {
1847 it2_ = it2_end_;
1848 BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
1849 -- it2_;
1850 current_ = 1;
1851 } else {
1852 -- it1_;
1853 }
1854 } else /* if (current_ == 1) */ {
1855 if (it2_ == it2_begin_ && begin_ == 0) {
1856 it1_ = it1_end_;
1857 BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
1858 -- it1_;
1859 current_ = 0;
1860 } else {
1861 -- it2_;
1862 }
1863 }
1864 return *this;
1865 }
1866 BOOST_UBLAS_INLINE
1867 const_iterator2 &operator += (difference_type n) {
1868 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1869 if (current_ == 0) {
1870 size_type d = (std::min) (n, it1_end_ - it1_);
1871 it1_ += d;
1872 n -= d;
1873 if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
1874 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1875 d = (std::min) (n, it2_end_ - it2_begin_);
1876 it2_ = it2_begin_ + d;
1877 n -= d;
1878 current_ = 1;
1879 }
1880 } else /* if (current_ == 1) */ {
1881 size_type d = (std::min) (n, it2_end_ - it2_);
1882 it2_ += d;
1883 n -= d;
1884 if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
1885 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1886 d = (std::min) (n, it1_end_ - it1_begin_);
1887 it1_ = it1_begin_ + d;
1888 n -= d;
1889 current_ = 0;
1890 }
1891 }
1892 BOOST_UBLAS_CHECK (n == 0, external_logic ());
1893 return *this;
1894 }
1895 BOOST_UBLAS_INLINE
1896 const_iterator2 &operator -= (difference_type n) {
1897 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1898 if (current_ == 0) {
1899 size_type d = (std::min) (n, it1_ - it1_begin_);
1900 it1_ -= d;
1901 n -= d;
1902 if (n > 0) {
1903 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1904 d = (std::min) (n, it2_end_ - it2_begin_);
1905 it2_ = it2_end_ - d;
1906 n -= d;
1907 current_ = 1;
1908 }
1909 } else /* if (current_ == 1) */ {
1910 size_type d = (std::min) (n, it2_ - it2_begin_);
1911 it2_ -= d;
1912 n -= d;
1913 if (n > 0) {
1914 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1915 d = (std::min) (n, it1_end_ - it1_begin_);
1916 it1_ = it1_end_ - d;
1917 n -= d;
1918 current_ = 0;
1919 }
1920 }
1921 BOOST_UBLAS_CHECK (n == 0, external_logic ());
1922 return *this;
1923 }
1924 BOOST_UBLAS_INLINE
1925 difference_type operator - (const const_iterator2 &it) const {
1926 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1927 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1928 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1929 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1930 if (current_ == 0 && it.current_ == 0) {
1931 return it1_ - it.it1_;
1932 } else if (current_ == 0 && it.current_ == 1) {
1933 if (end_ == 1 && it.end_ == 1) {
1934 return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
1935 } else /* if (end_ == 0 && it.end_ == 0) */ {
1936 return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
1937 }
1938
1939 } else if (current_ == 1 && it.current_ == 0) {
1940 if (end_ == 1 && it.end_ == 1) {
1941 return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
1942 } else /* if (end_ == 0 && it.end_ == 0) */ {
1943 return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
1944 }
1945 }
1946 /* current_ == 1 && it.current_ == 1 */ {
1947 return it2_ - it.it2_;
1948 }
1949 }
1950
1951 // Dereference
1952 BOOST_UBLAS_INLINE
1953 const_reference operator * () const {
1954 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1955 if (current_ == 0) {
1956 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1957 return *it1_;
1958 } else /* if (current_ == 1) */ {
1959 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1960 return *it2_;
1961 }
1962 }
1963 BOOST_UBLAS_INLINE
1964 const_reference operator [] (difference_type n) const {
1965 return *(*this + n);
1966 }
1967
1968#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1969 BOOST_UBLAS_INLINE
1970#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1971 typename self_type::
1972#endif
1973 const_iterator1 begin () const {
1974 return (*this) ().find1 (1, 0, index2 ());
1975 }
1976 BOOST_UBLAS_INLINE
1977#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1978 typename self_type::
1979#endif
1980 const_iterator1 cbegin () const {
1981 return begin ();
1982 }
1983 BOOST_UBLAS_INLINE
1984#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1985 typename self_type::
1986#endif
1987 const_iterator1 end () const {
1988 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1989 }
1990 BOOST_UBLAS_INLINE
1991#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1992 typename self_type::
1993#endif
1994 const_iterator1 cend () const {
1995 return end ();
1996 }
1997 BOOST_UBLAS_INLINE
1998#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1999 typename self_type::
2000#endif
2001 const_reverse_iterator1 rbegin () const {
2002 return const_reverse_iterator1 (end ());
2003 }
2004 BOOST_UBLAS_INLINE
2005#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2006 typename self_type::
2007#endif
2008 const_reverse_iterator1 crbegin () const {
2009 return rbegin ();
2010 }
2011 BOOST_UBLAS_INLINE
2012#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2013 typename self_type::
2014#endif
2015 const_reverse_iterator1 rend () const {
2016 return const_reverse_iterator1 (begin ());
2017 }
2018 BOOST_UBLAS_INLINE
2019#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2020 typename self_type::
2021#endif
2022 const_reverse_iterator1 crend () const {
2023 return rend ();
2024 }
2025#endif
2026
2027 // Indices
2028 BOOST_UBLAS_INLINE
2029 size_type index1 () const {
2030 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
2031 if (current_ == 0) {
2032 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
2033 return it1_.index2 ();
2034 } else /* if (current_ == 1) */ {
2035 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
2036 return it2_.index1 ();
2037 }
2038 }
2039 BOOST_UBLAS_INLINE
2040 size_type index2 () const {
2041 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
2042 if (current_ == 0) {
2043 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
2044 return it1_.index1 ();
2045 } else /* if (current_ == 1) */ {
2046 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
2047 return it2_.index2 ();
2048 }
2049 }
2050
2051 // Assignment
2052 BOOST_UBLAS_INLINE
2053 const_iterator2 &operator = (const const_iterator2 &it) {
2054 container_const_reference<self_type>::assign (&it ());
2055 begin_ = it.begin_;
2056 end_ = it.end_;
2057 current_ = it.current_;
2058 it1_begin_ = it.it1_begin_;
2059 it1_end_ = it.it1_end_;
2060 it1_ = it.it1_;
2061 it2_begin_ = it.it2_begin_;
2062 it2_end_ = it.it2_end_;
2063 it2_ = it.it2_;
2064 return *this;
2065 }
2066
2067 // Comparison
2068 BOOST_UBLAS_INLINE
2069 bool operator == (const const_iterator2 &it) const {
2070 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2071 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
2072 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
2073 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
2074 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
2075 (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
2076 }
2077 BOOST_UBLAS_INLINE
2078 bool operator < (const const_iterator2 &it) const {
2079 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2080 return it - *this > 0;
2081 }
2082
2083 private:
2084 int begin_;
2085 int end_;
2086 int current_;
2087 const_subiterator1_type it1_begin_;
2088 const_subiterator1_type it1_end_;
2089 const_subiterator1_type it1_;
2090 const_subiterator2_type it2_begin_;
2091 const_subiterator2_type it2_end_;
2092 const_subiterator2_type it2_;
2093 };
2094#endif
2095
2096 BOOST_UBLAS_INLINE
2097 const_iterator2 begin2 () const {
2098 return find2 (0, 0, 0);
2099 }
2100 BOOST_UBLAS_INLINE
2101 const_iterator2 cbegin2 () const {
2102 return begin2 ();
2103 }
2104 BOOST_UBLAS_INLINE
2105 const_iterator2 end2 () const {
2106 return find2 (0, 0, size2 ());
2107 }
2108 BOOST_UBLAS_INLINE
2109 const_iterator2 cend2 () const {
2110 return end2 ();
2111 }
2112
2113#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2114 class iterator2:
2115 public container_reference<symmetric_adaptor>,
2116 public random_access_iterator_base<typename iterator_restrict_traits<
2117 typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
2118 iterator2, value_type> {
2119 public:
2120 typedef typename subiterator2_type::value_type value_type;
2121 typedef typename subiterator2_type::difference_type difference_type;
2122 typedef typename subiterator2_type::reference reference;
2123 typedef typename subiterator2_type::pointer pointer;
2124
2125 typedef iterator1 dual_iterator_type;
2126 typedef reverse_iterator1 dual_reverse_iterator_type;
2127
2128 // Construction and destruction
2129 BOOST_UBLAS_INLINE
2130 iterator2 ():
2131 container_reference<self_type> (), it2_ () {}
2132 BOOST_UBLAS_INLINE
2133 iterator2 (self_type &m, const subiterator2_type &it2):
2134 container_reference<self_type> (m), it2_ (it2) {}
2135
2136 // Arithmetic
2137 BOOST_UBLAS_INLINE
2138 iterator2 &operator ++ () {
2139 ++ it2_;
2140 return *this;
2141 }
2142 BOOST_UBLAS_INLINE
2143 iterator2 &operator -- () {
2144 -- it2_;
2145 return *this;
2146 }
2147 BOOST_UBLAS_INLINE
2148 iterator2 &operator += (difference_type n) {
2149 it2_ += n;
2150 return *this;
2151 }
2152 BOOST_UBLAS_INLINE
2153 iterator2 &operator -= (difference_type n) {
2154 it2_ -= n;
2155 return *this;
2156 }
2157 BOOST_UBLAS_INLINE
2158 difference_type operator - (const iterator2 &it) const {
2159 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2160 return it2_ - it.it2_;
2161 }
2162
2163 // Dereference
2164 BOOST_UBLAS_INLINE
2165 reference operator * () const {
2166 return *it2_;
2167 }
2168 BOOST_UBLAS_INLINE
2169 reference operator [] (difference_type n) const {
2170 return *(*this + n);
2171 }
2172
2173#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2174 BOOST_UBLAS_INLINE
2175#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2176 typename self_type::
2177#endif
2178 iterator1 begin () const {
2179 return (*this) ().find1 (1, 0, index2 ());
2180 }
2181 BOOST_UBLAS_INLINE
2182#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2183 typename self_type::
2184#endif
2185 iterator1 end () const {
2186 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
2187 }
2188 BOOST_UBLAS_INLINE
2189#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2190 typename self_type::
2191#endif
2192 reverse_iterator1 rbegin () const {
2193 return reverse_iterator1 (end ());
2194 }
2195 BOOST_UBLAS_INLINE
2196#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2197 typename self_type::
2198#endif
2199 reverse_iterator1 rend () const {
2200 return reverse_iterator1 (begin ());
2201 }
2202#endif
2203
2204 // Indices
2205 BOOST_UBLAS_INLINE
2206 size_type index1 () const {
2207 return it2_.index1 ();
2208 }
2209 BOOST_UBLAS_INLINE
2210 size_type index2 () const {
2211 return it2_.index2 ();
2212 }
2213
2214 // Assignment
2215 BOOST_UBLAS_INLINE
2216 iterator2 &operator = (const iterator2 &it) {
2217 container_reference<self_type>::assign (&it ());
2218 it2_ = it.it2_;
2219 return *this;
2220 }
2221
2222 // Comparison
2223 BOOST_UBLAS_INLINE
2224 bool operator == (const iterator2 &it) const {
2225 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2226 return it2_ == it.it2_;
2227 }
2228 BOOST_UBLAS_INLINE
2229 bool operator < (const iterator2 &it) const {
2230 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2231 return it2_ < it.it2_;
2232 }
2233
2234 private:
2235 subiterator2_type it2_;
2236
2237 friend class const_iterator2;
2238 };
2239#endif
2240
2241 BOOST_UBLAS_INLINE
2242 iterator2 begin2 () {
2243 return find2 (0, 0, 0);
2244 }
2245 BOOST_UBLAS_INLINE
2246 iterator2 end2 () {
2247 return find2 (0, 0, size2 ());
2248 }
2249
2250 // Reverse iterators
2251
2252 BOOST_UBLAS_INLINE
2253 const_reverse_iterator1 rbegin1 () const {
2254 return const_reverse_iterator1 (end1 ());
2255 }
2256 BOOST_UBLAS_INLINE
2257 const_reverse_iterator1 crbegin1 () const {
2258 return rbegin1 ();
2259 }
2260 BOOST_UBLAS_INLINE
2261 const_reverse_iterator1 rend1 () const {
2262 return const_reverse_iterator1 (begin1 ());
2263 }
2264 BOOST_UBLAS_INLINE
2265 const_reverse_iterator1 crend1 () const {
2266 return rend1 ();
2267 }
2268
2269 BOOST_UBLAS_INLINE
2270 reverse_iterator1 rbegin1 () {
2271 return reverse_iterator1 (end1 ());
2272 }
2273 BOOST_UBLAS_INLINE
2274 reverse_iterator1 rend1 () {
2275 return reverse_iterator1 (begin1 ());
2276 }
2277
2278 BOOST_UBLAS_INLINE
2279 const_reverse_iterator2 rbegin2 () const {
2280 return const_reverse_iterator2 (end2 ());
2281 }
2282 BOOST_UBLAS_INLINE
2283 const_reverse_iterator2 crbegin2 () const {
2284 return rbegin2 ();
2285 }
2286 BOOST_UBLAS_INLINE
2287 const_reverse_iterator2 rend2 () const {
2288 return const_reverse_iterator2 (begin2 ());
2289 }
2290 BOOST_UBLAS_INLINE
2291 const_reverse_iterator2 crend2 () const {
2292 return rend2 ();
2293 }
2294
2295 BOOST_UBLAS_INLINE
2296 reverse_iterator2 rbegin2 () {
2297 return reverse_iterator2 (end2 ());
2298 }
2299 BOOST_UBLAS_INLINE
2300 reverse_iterator2 rend2 () {
2301 return reverse_iterator2 (begin2 ());
2302 }
2303
2304 // Serialization
2305 template<class Archive>
2306 void serialize(Archive & ar, const unsigned int){
2307
2308 serialization::collection_size_type s1 (size1() );
2309 serialization::collection_size_type s2 (size2() );
2310
2311 ar & serialization::make_nvp("size1",s1)
2312 & serialization::make_nvp("size2",s2);
2313
2314 if (Archive::is_loading::value) {
2315 }
2316 ar & serialization::make_nvp("data",data_);
2317 }
2318
2319
2320 private:
2321 matrix_closure_type data_;
2322 };
2323
2324 // Specialization for temporary_traits
2325 template <class M, class TRI>
2326 struct vector_temporary_traits< symmetric_adaptor<M, TRI> >
2327 : vector_temporary_traits< M > {} ;
2328 template <class M, class TRI>
2329 struct vector_temporary_traits< const symmetric_adaptor<M, TRI> >
2330 : vector_temporary_traits< M > {} ;
2331
2332 template <class M, class TRI>
2333 struct matrix_temporary_traits< symmetric_adaptor<M, TRI> >
2334 : matrix_temporary_traits< M > {} ;
2335 template <class M, class TRI>
2336 struct matrix_temporary_traits< const symmetric_adaptor<M, TRI> >
2337 : matrix_temporary_traits< M > {} ;
2338
2339}}}
2340
2341#endif