Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/numeric/ublas/hermitian.hpp @ 30

Last change on this file since 30 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

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