source: XIOS/dev/dev_olga/src/extern/boost/include/boost/numeric/ublas/hermitian.hpp @ 1022

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