]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/boost/boost/numeric/ublas/hermitian.hpp
Add subset of boost library headers needed for compilation on PowerPC
[eurobot/public.git] / src / boost / boost / numeric / ublas / hermitian.hpp
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
23 namespace 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