- Main Page
- Related Pages
- Classes
- Files

- File List

# hermitian.hpp

    00001 //
    00002 //  Copyright (c) 2000-2010
    00003 //  Joerg Walter, Mathias Koch, David Bellot
    00004 //
    00005 //  Distributed under the Boost Software License, Version 1.0. (See
    00006 //  accompanying file LICENSE_1_0.txt or copy at
    00007 //  http://www.boost.org/LICENSE_1_0.txt)
    00008 //
    00009 //  The authors gratefully acknowledge the support of
    00010 //  GeNeSys mbH & Co. KG in producing this work.
    00011 //
    00012
    00013 #ifndef BOOST_UBLAS_HERMITIAN_H
    00014 #define BOOST_UBLAS_HERMITIAN_H
    00015
    00016 #include <boost/numeric/ublas/matrix.hpp>
    00017 #include <boost/numeric/ublas/triangular.hpp>  // for resize_preserve
    00018 #include <boost/numeric/ublas/detail/temporary.hpp>
    00019
    00020 // Iterators based on ideas of Jeremy Siek
    00021 // Hermitian matrices are square. Thanks to Peter Schmitteckert for spotting this.
    00022
    00023 namespace boost { namespace numeric { namespace ublas {
    00024
    00025     template<class M>
    00026     bool is_hermitian (const M &m) {
    00027         typedef typename M::size_type size_type;
    00028
    00029         if (m.size1 () != m.size2 ())
    00030             return false;
    00031         size_type size = BOOST_UBLAS_SAME (m.size1 (), m.size2 ());
    00032         for (size_type i = 0; i < size; ++ i) {
    00033             for (size_type j = i; j < size; ++ j) {
    00034                 if (m (i, j) != conj (m (j, i)))
    00035                     return false;
    00036             }
    00037         }
    00038         return true;
    00039     }
    00040
    00041 #ifdef BOOST_UBLAS_STRICT_HERMITIAN
    00042
    00043     template<class M>
    00044     class hermitian_matrix_element:
    00045        public container_reference<M> {
    00046     public:
    00047         typedef M matrix_type;
    00048         typedef typename M::size_type size_type;
    00049         typedef typename M::value_type value_type;
    00050         typedef const value_type &const_reference;
    00051         typedef value_type &reference;
    00052         typedef value_type *pointer;
    00053
    00054         // Construction and destruction
    00055         BOOST_UBLAS_INLINE
    00056         hermitian_matrix_element (matrix_type &m, size_type i, size_type j, value_type d):
    00057             container_reference<matrix_type> (m), i_ (i), j_ (j), d_ (d), dirty_ (false) {}
    00058         BOOST_UBLAS_INLINE
    00059         ~hermitian_matrix_element () {
    00060             if (dirty_)
    00061                 (*this) ().insert_element (i_, j_, d_);
    00062         }
    00063
    00064         // Assignment
    00065         BOOST_UBLAS_INLINE
    00066         hermitian_matrix_element &operator = (const hermitian_matrix_element &p) {
    00067             // Overide the implict copy assignment
    00068             d_ = p.d_;
    00069             dirty_ = true;
    00070             return *this;
    00071         }
    00072         template<class D>
    00073         BOOST_UBLAS_INLINE
    00074         hermitian_matrix_element &operator = (const D &d) {
    00075             d_ = d;
    00076             dirty_ = true;
    00077             return *this;
    00078         }
    00079         template<class D>
    00080         BOOST_UBLAS_INLINE
    00081         hermitian_matrix_element &operator += (const D &d) {
    00082             d_ += d;
    00083             dirty_ = true;
    00084             return *this;
    00085         }
    00086         template<class D>
    00087         BOOST_UBLAS_INLINE
    00088         hermitian_matrix_element &operator -= (const D &d) {
    00089             d_ -= d;
    00090             dirty_ = true;
    00091             return *this;
    00092         }
    00093         template<class D>
    00094         BOOST_UBLAS_INLINE
    00095         hermitian_matrix_element &operator *= (const D &d) {
    00096             d_ *= d;
    00097             dirty_ = true;
    00098             return *this;
    00099         }
    00100         template<class D>
    00101         BOOST_UBLAS_INLINE
    00102         hermitian_matrix_element &operator /= (const D &d) {
    00103             d_ /= d;
    00104             dirty_ = true;
    00105             return *this;
    00106         }
    00107
    00108         // Comparison
    00109         template<class D>
    00110         BOOST_UBLAS_INLINE
    00111         bool operator == (const D &d) const {
    00112             return d_ == d;
    00113         }
    00114         template<class D>
    00115         BOOST_UBLAS_INLINE
    00116         bool operator != (const D &d) const {
    00117             return d_ != d;
    00118         }
    00119
    00120         // Conversion
    00121         BOOST_UBLAS_INLINE
    00122         operator const_reference () const {
    00123             return d_;
    00124         }
    00125
    00126         // Swapping
    00127         BOOST_UBLAS_INLINE
    00128         void swap (hermitian_matrix_element p) {
    00129             if (this != &p) {
    00130                 dirty_ = true;
    00131                 p.dirty_ = true;
    00132                 std::swap (d_, p.d_);
    00133             }
    00134         }
    00135         BOOST_UBLAS_INLINE
    00136         friend void swap (hermitian_matrix_element p1, hermitian_matrix_element p2) {
    00137             p1.swap (p2);
    00138         }
    00139
    00140     private:
    00141         size_type i_;
    00142         size_type j_;
    00143         value_type d_;
    00144         bool dirty_;
    00145     };
    00146
    00147     template<class M>
    00148     struct type_traits<hermitian_matrix_element<M> > {
    00149         typedef typename M::value_type element_type;
    00150         typedef type_traits<hermitian_matrix_element<M> > self_type;
    00151         typedef typename type_traits<element_type>::value_type value_type;
    00152         typedef typename type_traits<element_type>::const_reference const_reference;
    00153         typedef hermitian_matrix_element<M> reference;
    00154         typedef typename type_traits<element_type>::real_type real_type;
    00155         typedef typename type_traits<element_type>::precision_type precision_type;
    00156
    00157         static const unsigned plus_complexity = type_traits<element_type>::plus_complexity;
    00158         static const unsigned multiplies_complexity = type_traits<element_type>::multiplies_complexity;
    00159
    00160         static
    00161         BOOST_UBLAS_INLINE
    00162         real_type real (const_reference t) {
    00163             return type_traits<element_type>::real (t);
    00164         }
    00165         static
    00166         BOOST_UBLAS_INLINE
    00167         real_type imag (const_reference t) {
    00168             return type_traits<element_type>::imag (t);
    00169         }
    00170         static
    00171         BOOST_UBLAS_INLINE
    00172         value_type conj (const_reference t) {
    00173             return type_traits<element_type>::conj (t);
    00174         }
    00175
    00176         static
    00177         BOOST_UBLAS_INLINE
    00178         real_type type_abs (const_reference t) {
    00179             return type_traits<element_type>::type_abs (t);
    00180         }
    00181         static
    00182         BOOST_UBLAS_INLINE
    00183         value_type type_sqrt (const_reference t) {
    00184             return type_traits<element_type>::type_sqrt (t);
    00185         }
    00186
    00187         static
    00188         BOOST_UBLAS_INLINE
    00189         real_type norm_1 (const_reference t) {
    00190             return type_traits<element_type>::norm_1 (t);
    00191         }
    00192         static
    00193         BOOST_UBLAS_INLINE
    00194         real_type norm_2 (const_reference t) {
    00195             return type_traits<element_type>::norm_2 (t);
    00196         }
    00197         static
    00198         BOOST_UBLAS_INLINE
    00199         real_type norm_inf (const_reference t) {
    00200             return type_traits<element_type>::norm_inf (t);
    00201         }
    00202
    00203         static
    00204         BOOST_UBLAS_INLINE
    00205         bool equals (const_reference t1, const_reference t2) {
    00206             return type_traits<element_type>::equals (t1, t2);
    00207         }
    00208     };
    00209
    00210     template<class M1, class T2>
    00211     struct promote_traits<hermitian_matrix_element<M1>, T2> {
    00212         typedef typename promote_traits<typename hermitian_matrix_element<M1>::value_type, T2>::promote_type promote_type;
    00213     };
    00214     template<class T1, class M2>
    00215     struct promote_traits<T1, hermitian_matrix_element<M2> > {
    00216         typedef typename promote_traits<T1, typename hermitian_matrix_element<M2>::value_type>::promote_type promote_type;
    00217     };
    00218     template<class M1, class M2>
    00219     struct promote_traits<hermitian_matrix_element<M1>, hermitian_matrix_element<M2> > {
    00220         typedef typename promote_traits<typename hermitian_matrix_element<M1>::value_type,
    00221                                         typename hermitian_matrix_element<M2>::value_type>::promote_type promote_type;
    00222     };
    00223
    00224 #endif
    00225
    00243     template<class T, class TRI, class L, class A>
    00244     class hermitian_matrix:
    00245         public matrix_container<hermitian_matrix<T, TRI, L, A> > {
    00246
    00247         typedef T &true_reference;
    00248         typedef T *pointer;
    00249         typedef TRI triangular_type;
    00250         typedef L layout_type;
    00251         typedef hermitian_matrix<T, TRI, L, A> self_type;
    00252     public:
    00253 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    00254         using matrix_container<self_type>::operator ();
    00255 #endif
    00256         typedef typename A::size_type size_type;
    00257         typedef typename A::difference_type difference_type;
    00258         typedef T value_type;
    00259         // FIXME no better way to not return the address of a temporary?
    00260         // typedef const T &const_reference;
    00261         typedef const T const_reference;
    00262 #ifndef BOOST_UBLAS_STRICT_HERMITIAN
    00263         typedef T &reference;
    00264 #else
    00265         typedef hermitian_matrix_element<self_type> reference;
    00266 #endif
    00267         typedef A array_type;
    00268
    00269         typedef const matrix_reference<const self_type> const_closure_type;
    00270         typedef matrix_reference<self_type> closure_type;
    00271         typedef vector<T, A> vector_temporary_type;
    00272         typedef matrix<T, L, A> matrix_temporary_type;  // general sub-matrix
    00273         typedef packed_tag storage_category;
    00274         typedef typename L::orientation_category orientation_category;
    00275
    00276         // Construction and destruction
    00277         BOOST_UBLAS_INLINE
    00278         hermitian_matrix ():
    00279             matrix_container<self_type> (),
    00280             size_ (0), data_ (0) {}
    00281         BOOST_UBLAS_INLINE
    00282         hermitian_matrix (size_type size):
    00283             matrix_container<self_type> (),
    00284             size_ (BOOST_UBLAS_SAME (size, size)), data_ (triangular_type::packed_size (layout_type (), size, size)) {
    00285         }
    00286         BOOST_UBLAS_INLINE
    00287         hermitian_matrix (size_type size1, size_type size2):
    00288             matrix_container<self_type> (),
    00289             size_ (BOOST_UBLAS_SAME (size1, size2)), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
    00290         }
    00291         BOOST_UBLAS_INLINE
    00292         hermitian_matrix (size_type size, const array_type &data):
    00293             matrix_container<self_type> (),
    00294             size_ (size), data_ (data) {}
    00295         BOOST_UBLAS_INLINE
    00296         hermitian_matrix (const hermitian_matrix &m):
    00297             matrix_container<self_type> (),
    00298             size_ (m.size_), data_ (m.data_) {}
    00299         template<class AE>
    00300         BOOST_UBLAS_INLINE
    00301         hermitian_matrix (const matrix_expression<AE> &ae):
    00302             matrix_container<self_type> (),
    00303             size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())),
    00304             data_ (triangular_type::packed_size (layout_type (), size_, size_)) {
    00305             matrix_assign<scalar_assign> (*this, ae);
    00306         }
    00307
    00308         // Accessors
    00309         BOOST_UBLAS_INLINE
    00310         size_type size1 () const {
    00311             return size_;
    00312         }
    00313         BOOST_UBLAS_INLINE
    00314         size_type size2 () const {
    00315             return size_;
    00316         }
    00317
    00318         // Storage accessors
    00319         BOOST_UBLAS_INLINE
    00320         const array_type &data () const {
    00321             return data_;
    00322         }
    00323         BOOST_UBLAS_INLINE
    00324         array_type &data () {
    00325             return data_;
    00326         }
    00327
    00328         // Resizing
    00329         BOOST_UBLAS_INLINE
    00330         void resize (size_type size, bool preserve = true) {
    00331             if (preserve) {
    00332                 self_type temporary (size, size);
    00333                 detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary);
    00334             }
    00335             else {
    00336                 data ().resize (triangular_type::packed_size (layout_type (), size, size));
    00337                 size_ = size;
    00338             }
    00339         }
    00340         BOOST_UBLAS_INLINE
    00341         void resize (size_type size1, size_type size2, bool preserve = true) {
    00342             resize (BOOST_UBLAS_SAME (size1, size2), preserve);
    00343         }
    00344         BOOST_UBLAS_INLINE
    00345         void resize_packed_preserve (size_type size) {
    00346             size_ = BOOST_UBLAS_SAME (size, size);
    00347             data ().resize (triangular_type::packed_size (layout_type (), size_, size_), value_type ());
    00348         }
    00349
    00350         // Element access
    00351         BOOST_UBLAS_INLINE
    00352         const_reference operator () (size_type i, size_type j) const {
    00353             BOOST_UBLAS_CHECK (i < size_, bad_index ());
    00354             BOOST_UBLAS_CHECK (j < size_, bad_index ());
    00355             // if (i == j)
    00356             //    return type_traits<value_type>::real (data () [triangular_type::element (layout_type (), i, size_, i, size_)]);
    00357             // else
    00358             if (triangular_type::other (i, j))
    00359                 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
    00360             else
    00361                 return type_traits<value_type>::conj (data () [triangular_type::element (layout_type (), j, size_, i, size_)]);
    00362         }
    00363         BOOST_UBLAS_INLINE
    00364         true_reference at_element (size_type i, size_type j) {
    00365             BOOST_UBLAS_CHECK (i < size_, bad_index ());
    00366             BOOST_UBLAS_CHECK (j < size_, bad_index ());
    00367             BOOST_UBLAS_CHECK (triangular_type::other (i, j), bad_index ());
    00368             return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
    00369         }
    00370         BOOST_UBLAS_INLINE
    00371         reference operator () (size_type i, size_type j) {
    00372 #ifndef BOOST_UBLAS_STRICT_HERMITIAN
    00373             if (!triangular_type::other (i, j)) {
    00374                 bad_index ().raise ();
    00375                 // NEVER reached
    00376             }
    00377             return at_element (i, j);
    00378 #else
    00379         if (triangular_type::other (i, j))
    00380             return reference (*this, i, j, data () [triangular_type::element (layout_type (), i, size_, j, size_)]);
    00381         else
    00382             return reference (*this, i, j, type_traits<value_type>::conj (data () [triangular_type::element (layout_type (), j, size_, i, size_)]));
    00383 #endif
    00384         }
    00385
    00386         // Element assignemnt
    00387         BOOST_UBLAS_INLINE
    00388         true_reference insert_element (size_type i, size_type j, const_reference t) {
    00389             BOOST_UBLAS_CHECK (i < size_, bad_index ());
    00390             BOOST_UBLAS_CHECK (j < size_, bad_index ());
    00391             if (triangular_type::other (i, j)) {
    00392                 return (data () [triangular_type::element (layout_type (), i, size_, j, size_)] = t);
    00393             } else {
    00394                 return (data () [triangular_type::element (layout_type (), j, size_, i, size_)] = type_traits<value_type>::conj (t));
    00395             }
    00396         }
    00397         BOOST_UBLAS_INLINE
    00398         void erase_element (size_type i, size_type j) {
    00399             BOOST_UBLAS_CHECK (i < size_, bad_index ());
    00400             BOOST_UBLAS_CHECK (j < size_, bad_index ());
    00401             data () [triangular_type::element (layout_type (), i, size_, j, size_)] = value_type/*zero*/();
    00402         }
    00403
    00404         // Zeroing
    00405         BOOST_UBLAS_INLINE
    00406         void clear () {
    00407             std::fill (data ().begin (), data ().end (), value_type/*zero*/());
    00408         }
    00409
    00410         // Assignment
    00411         BOOST_UBLAS_INLINE
    00412         hermitian_matrix &operator = (const hermitian_matrix &m) {
    00413             size_ = m.size_;
    00414             data () = m.data ();
    00415             return *this;
    00416         }
    00417         BOOST_UBLAS_INLINE
    00418         hermitian_matrix &assign_temporary (hermitian_matrix &m) {
    00419             swap (m);
    00420             return *this;
    00421         }
    00422         template<class AE>
    00423         BOOST_UBLAS_INLINE
    00424         hermitian_matrix &operator = (const matrix_expression<AE> &ae) {
    00425             self_type temporary (ae);
    00426             return assign_temporary (temporary);
    00427         }
    00428         template<class AE>
    00429         BOOST_UBLAS_INLINE
    00430         hermitian_matrix &assign (const matrix_expression<AE> &ae) {
    00431             matrix_assign<scalar_assign> (*this, ae);
    00432             return *this;
    00433         }
    00434         template<class AE>
    00435         BOOST_UBLAS_INLINE
    00436         hermitian_matrix& operator += (const matrix_expression<AE> &ae) {
    00437             self_type temporary (*this + ae);
    00438             return assign_temporary (temporary);
    00439         }
    00440         template<class AE>
    00441         BOOST_UBLAS_INLINE
    00442         hermitian_matrix &plus_assign (const matrix_expression<AE> &ae) {
    00443             matrix_assign<scalar_plus_assign> (*this, ae);
    00444             return *this;
    00445         }
    00446         template<class AE>
    00447         BOOST_UBLAS_INLINE
    00448         hermitian_matrix& operator -= (const matrix_expression<AE> &ae) {
    00449             self_type temporary (*this - ae);
    00450             return assign_temporary (temporary);
    00451         }
    00452         template<class AE>
    00453         BOOST_UBLAS_INLINE
    00454         hermitian_matrix &minus_assign (const matrix_expression<AE> &ae) {
    00455             matrix_assign<scalar_minus_assign> (*this, ae);
    00456             return *this;
    00457         }
    00458         template<class AT>
    00459         BOOST_UBLAS_INLINE
    00460         hermitian_matrix& operator *= (const AT &at) {
    00461             // Multiplication is only allowed for real scalars,
    00462             // otherwise the resulting matrix isn't hermitian.
    00463             // Thanks to Peter Schmitteckert for spotting this.
    00464             BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
    00465             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
    00466             return *this;
    00467         }
    00468         template<class AT>
    00469         BOOST_UBLAS_INLINE
    00470         hermitian_matrix& operator /= (const AT &at) {
    00471             // Multiplication is only allowed for real scalars,
    00472             // otherwise the resulting matrix isn't hermitian.
    00473             // Thanks to Peter Schmitteckert for spotting this.
    00474             BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
    00475             matrix_assign_scalar<scalar_divides_assign> (*this, at);
    00476             return *this;
    00477         }
    00478
    00479         // Swapping
    00480         BOOST_UBLAS_INLINE
    00481         void swap (hermitian_matrix &m) {
    00482             if (this != &m) {
    00483                 std::swap (size_, m.size_);
    00484                 data ().swap (m.data ());
    00485             }
    00486         }
    00487         BOOST_UBLAS_INLINE
    00488         friend void swap (hermitian_matrix &m1, hermitian_matrix &m2) {
    00489             m1.swap (m2);
    00490         }
    00491
    00492         // Iterator types
    00493 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00494         typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
    00495         typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
    00496         typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
    00497         typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
    00498 #else
    00499         class const_iterator1;
    00500         class iterator1;
    00501         class const_iterator2;
    00502         class iterator2;
    00503 #endif
    00504         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    00505         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
    00506         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    00507         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
    00508
    00509         // Element lookup
    00510         BOOST_UBLAS_INLINE
    00511         const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
    00512             return const_iterator1 (*this, i, j);
    00513         }
    00514         BOOST_UBLAS_INLINE
    00515         iterator1 find1 (int rank, size_type i, size_type j) {
    00516             if (rank == 1)
    00517                 i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
    00518             if (rank == 0)
    00519                 i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
    00520             return iterator1 (*this, i, j);
    00521         }
    00522         BOOST_UBLAS_INLINE
    00523         const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
    00524             return const_iterator2 (*this, i, j);
    00525         }
    00526         BOOST_UBLAS_INLINE
    00527         iterator2 find2 (int rank, size_type i, size_type j) {
    00528             if (rank == 1)
    00529                 j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
    00530             if (rank == 0)
    00531                 j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
    00532             return iterator2 (*this, i, j);
    00533         }
    00534
    00535         // Iterators simply are indices.
    00536
    00537 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00538         class const_iterator1:
    00539             public container_const_reference<hermitian_matrix>,
    00540             public random_access_iterator_base<packed_random_access_iterator_tag,
    00541                                                const_iterator1, value_type> {
    00542         public:
    00543             typedef typename hermitian_matrix::value_type value_type;
    00544             typedef typename hermitian_matrix::difference_type difference_type;
    00545             typedef typename hermitian_matrix::const_reference reference;
    00546             typedef const typename hermitian_matrix::pointer pointer;
    00547
    00548             typedef const_iterator2 dual_iterator_type;
    00549             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    00550
    00551             // Construction and destruction
    00552             BOOST_UBLAS_INLINE
    00553             const_iterator1 ():
    00554                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    00555             BOOST_UBLAS_INLINE
    00556             const_iterator1 (const self_type &m, size_type it1, size_type it2):
    00557                 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
    00558             BOOST_UBLAS_INLINE
    00559             const_iterator1 (const iterator1 &it):
    00560                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
    00561
    00562             // Arithmetic
    00563             BOOST_UBLAS_INLINE
    00564             const_iterator1 &operator ++ () {
    00565                 ++ it1_;
    00566                 return *this;
    00567             }
    00568             BOOST_UBLAS_INLINE
    00569             const_iterator1 &operator -- () {
    00570                 -- it1_;
    00571                 return *this;
    00572             }
    00573             BOOST_UBLAS_INLINE
    00574             const_iterator1 &operator += (difference_type n) {
    00575                 it1_ += n;
    00576                 return *this;
    00577             }
    00578             BOOST_UBLAS_INLINE
    00579             const_iterator1 &operator -= (difference_type n) {
    00580                 it1_ -= n;
    00581                 return *this;
    00582             }
    00583             BOOST_UBLAS_INLINE
    00584             difference_type operator - (const const_iterator1 &it) const {
    00585                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00586                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    00587                 return it1_ - it.it1_;
    00588             }
    00589
    00590             // Dereference
    00591             BOOST_UBLAS_INLINE
    00592             const_reference operator * () const {
    00593                 return (*this) () (it1_, it2_);
    00594             }
    00595             BOOST_UBLAS_INLINE
    00596             const_reference operator [] (difference_type n) const {
    00597                 return *(*this + n);
    00598             }
    00599
    00600 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00601             BOOST_UBLAS_INLINE
    00602 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00603             typename self_type::
    00604 #endif
    00605             const_iterator2 begin () const {
    00606                 return (*this) ().find2 (1, it1_, 0);
    00607             }
    00608             BOOST_UBLAS_INLINE
    00609 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00610             typename self_type::
    00611 #endif
    00612             const_iterator2 end () const {
    00613                 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
    00614             }
    00615             BOOST_UBLAS_INLINE
    00616 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00617             typename self_type::
    00618 #endif
    00619             const_reverse_iterator2 rbegin () const {
    00620                 return const_reverse_iterator2 (end ());
    00621             }
    00622             BOOST_UBLAS_INLINE
    00623 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00624             typename self_type::
    00625 #endif
    00626             const_reverse_iterator2 rend () const {
    00627                 return const_reverse_iterator2 (begin ());
    00628             }
    00629 #endif
    00630
    00631             // Indices
    00632             BOOST_UBLAS_INLINE
    00633             size_type index1 () const {
    00634                 return it1_;
    00635             }
    00636             BOOST_UBLAS_INLINE
    00637             size_type index2 () const {
    00638                 return it2_;
    00639             }
    00640
    00641             // Assignment
    00642             BOOST_UBLAS_INLINE
    00643             const_iterator1 &operator = (const const_iterator1 &it) {
    00644                 container_const_reference<self_type>::assign (&it ());
    00645                 it1_ = it.it1_;
    00646                 it2_ = it.it2_;
    00647                 return *this;
    00648             }
    00649
    00650             // Comparison
    00651             BOOST_UBLAS_INLINE
    00652             bool operator == (const const_iterator1 &it) const {
    00653                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00654                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    00655                 return it1_ == it.it1_;
    00656             }
    00657             BOOST_UBLAS_INLINE
    00658             bool operator < (const const_iterator1 &it) const {
    00659                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00660                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    00661                 return it1_ < it.it1_;
    00662             }
    00663
    00664         private:
    00665             size_type it1_;
    00666             size_type it2_;
    00667         };
    00668 #endif
    00669
    00670         BOOST_UBLAS_INLINE
    00671         const_iterator1 begin1 () const {
    00672             return find1 (0, 0, 0);
    00673         }
    00674         BOOST_UBLAS_INLINE
    00675         const_iterator1 end1 () const {
    00676             return find1 (0, size_, 0);
    00677         }
    00678
    00679 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00680         class iterator1:
    00681             public container_reference<hermitian_matrix>,
    00682             public random_access_iterator_base<packed_random_access_iterator_tag,
    00683                                                iterator1, value_type> {
    00684         public:
    00685             typedef typename hermitian_matrix::value_type value_type;
    00686             typedef typename hermitian_matrix::difference_type difference_type;
    00687             typedef typename hermitian_matrix::true_reference reference;
    00688             typedef typename hermitian_matrix::pointer pointer;
    00689
    00690             typedef iterator2 dual_iterator_type;
    00691             typedef reverse_iterator2 dual_reverse_iterator_type;
    00692
    00693             // Construction and destruction
    00694             BOOST_UBLAS_INLINE
    00695             iterator1 ():
    00696                 container_reference<self_type> (), it1_ (), it2_ () {}
    00697             BOOST_UBLAS_INLINE
    00698             iterator1 (self_type &m, size_type it1, size_type it2):
    00699                 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
    00700
    00701             // Arithmetic
    00702             BOOST_UBLAS_INLINE
    00703             iterator1 &operator ++ () {
    00704                 ++ it1_;
    00705                 return *this;
    00706             }
    00707             BOOST_UBLAS_INLINE
    00708             iterator1 &operator -- () {
    00709                 -- it1_;
    00710                 return *this;
    00711             }
    00712             BOOST_UBLAS_INLINE
    00713             iterator1 &operator += (difference_type n) {
    00714                 it1_ += n;
    00715                 return *this;
    00716             }
    00717             BOOST_UBLAS_INLINE
    00718             iterator1 &operator -= (difference_type n) {
    00719                 it1_ -= n;
    00720                 return *this;
    00721             }
    00722             BOOST_UBLAS_INLINE
    00723             difference_type operator - (const iterator1 &it) const {
    00724                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00725                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    00726                 return it1_ - it.it1_;
    00727             }
    00728
    00729             // Dereference
    00730             BOOST_UBLAS_INLINE
    00731             reference operator * () const {
    00732                 return (*this) ().at_element (it1_, it2_);
    00733             }
    00734             BOOST_UBLAS_INLINE
    00735             reference operator [] (difference_type n) const {
    00736                 return *(*this + n);
    00737             }
    00738
    00739 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00740             BOOST_UBLAS_INLINE
    00741 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00742             typename self_type::
    00743 #endif
    00744             iterator2 begin () const {
    00745                 return (*this) ().find2 (1, it1_, 0);
    00746             }
    00747             BOOST_UBLAS_INLINE
    00748 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00749             typename self_type::
    00750 #endif
    00751             iterator2 end () const {
    00752                 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
    00753             }
    00754             BOOST_UBLAS_INLINE
    00755 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00756             typename self_type::
    00757 #endif
    00758             reverse_iterator2 rbegin () const {
    00759                 return reverse_iterator2 (end ());
    00760             }
    00761             BOOST_UBLAS_INLINE
    00762 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00763             typename self_type::
    00764 #endif
    00765             reverse_iterator2 rend () const {
    00766                 return reverse_iterator2 (begin ());
    00767             }
    00768 #endif
    00769
    00770             // Indices
    00771             BOOST_UBLAS_INLINE
    00772             size_type index1 () const {
    00773                 return it1_;
    00774             }
    00775             BOOST_UBLAS_INLINE
    00776             size_type index2 () const {
    00777                 return it2_;
    00778             }
    00779
    00780             // Assignment
    00781             BOOST_UBLAS_INLINE
    00782             iterator1 &operator = (const iterator1 &it) {
    00783                 container_reference<self_type>::assign (&it ());
    00784                 it1_ = it.it1_;
    00785                 it2_ = it.it2_;
    00786                 return *this;
    00787             }
    00788
    00789             // Comparison
    00790             BOOST_UBLAS_INLINE
    00791             bool operator == (const iterator1 &it) const {
    00792                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00793                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    00794                 return it1_ == it.it1_;
    00795             }
    00796             BOOST_UBLAS_INLINE
    00797             bool operator < (const iterator1 &it) const {
    00798                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00799                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    00800                 return it1_ < it.it1_;
    00801             }
    00802
    00803         private:
    00804             size_type it1_;
    00805             size_type it2_;
    00806
    00807             friend class const_iterator1;
    00808         };
    00809 #endif
    00810
    00811         BOOST_UBLAS_INLINE
    00812         iterator1 begin1 () {
    00813             return find1 (0, 0, 0);
    00814         }
    00815         BOOST_UBLAS_INLINE
    00816         iterator1 end1 () {
    00817             return find1 (0, size_, 0);
    00818         }
    00819
    00820 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00821         class const_iterator2:
    00822             public container_const_reference<hermitian_matrix>,
    00823             public random_access_iterator_base<packed_random_access_iterator_tag,
    00824                                                const_iterator2, value_type> {
    00825         public:
    00826             typedef typename hermitian_matrix::value_type value_type;
    00827             typedef typename hermitian_matrix::difference_type difference_type;
    00828             typedef typename hermitian_matrix::const_reference reference;
    00829             typedef const typename hermitian_matrix::pointer pointer;
    00830
    00831             typedef const_iterator1 dual_iterator_type;
    00832             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    00833
    00834             // Construction and destruction
    00835             BOOST_UBLAS_INLINE
    00836             const_iterator2 ():
    00837                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    00838             BOOST_UBLAS_INLINE
    00839             const_iterator2 (const self_type &m, size_type it1, size_type it2):
    00840                 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
    00841             BOOST_UBLAS_INLINE
    00842             const_iterator2 (const iterator2 &it):
    00843                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
    00844
    00845             // Arithmetic
    00846             BOOST_UBLAS_INLINE
    00847             const_iterator2 &operator ++ () {
    00848                 ++ it2_;
    00849                 return *this;
    00850             }
    00851             BOOST_UBLAS_INLINE
    00852             const_iterator2 &operator -- () {
    00853                 -- it2_;
    00854                 return *this;
    00855             }
    00856             BOOST_UBLAS_INLINE
    00857             const_iterator2 &operator += (difference_type n) {
    00858                 it2_ += n;
    00859                 return *this;
    00860             }
    00861             BOOST_UBLAS_INLINE
    00862             const_iterator2 &operator -= (difference_type n) {
    00863                 it2_ -= n;
    00864                 return *this;
    00865             }
    00866             BOOST_UBLAS_INLINE
    00867             difference_type operator - (const const_iterator2 &it) const {
    00868                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00869                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    00870                 return it2_ - it.it2_;
    00871             }
    00872
    00873             // Dereference
    00874             BOOST_UBLAS_INLINE
    00875             const_reference operator * () const {
    00876                 return (*this) () (it1_, it2_);
    00877             }
    00878             BOOST_UBLAS_INLINE
    00879             const_reference operator [] (difference_type n) const {
    00880                 return *(*this + n);
    00881             }
    00882
    00883 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00884             BOOST_UBLAS_INLINE
    00885 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00886             typename self_type::
    00887 #endif
    00888             const_iterator1 begin () const {
    00889                 return (*this) ().find1 (1, 0, it2_);
    00890             }
    00891             BOOST_UBLAS_INLINE
    00892 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00893             typename self_type::
    00894 #endif
    00895             const_iterator1 end () const {
    00896                 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
    00897             }
    00898             BOOST_UBLAS_INLINE
    00899 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00900             typename self_type::
    00901 #endif
    00902             const_reverse_iterator1 rbegin () const {
    00903                 return const_reverse_iterator1 (end ());
    00904             }
    00905             BOOST_UBLAS_INLINE
    00906 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00907             typename self_type::
    00908 #endif
    00909             const_reverse_iterator1 rend () const {
    00910                 return const_reverse_iterator1 (begin ());
    00911             }
    00912 #endif
    00913
    00914             // Indices
    00915             BOOST_UBLAS_INLINE
    00916             size_type index1 () const {
    00917                 return it1_;
    00918             }
    00919             BOOST_UBLAS_INLINE
    00920             size_type index2 () const {
    00921                 return it2_;
    00922             }
    00923
    00924             // Assignment
    00925             BOOST_UBLAS_INLINE
    00926             const_iterator2 &operator = (const const_iterator2 &it) {
    00927                 container_const_reference<self_type>::assign (&it ());
    00928                 it1_ = it.it1_;
    00929                 it2_ = it.it2_;
    00930                 return *this;
    00931             }
    00932
    00933             // Comparison
    00934             BOOST_UBLAS_INLINE
    00935             bool operator == (const const_iterator2 &it) const {
    00936                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00937                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    00938                 return it2_ == it.it2_;
    00939             }
    00940             BOOST_UBLAS_INLINE
    00941             bool operator < (const const_iterator2 &it) const {
    00942                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00943                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    00944                 return it2_ < it.it2_;
    00945             }
    00946
    00947         private:
    00948             size_type it1_;
    00949             size_type it2_;
    00950         };
    00951 #endif
    00952
    00953         BOOST_UBLAS_INLINE
    00954         const_iterator2 begin2 () const {
    00955             return find2 (0, 0, 0);
    00956         }
    00957         BOOST_UBLAS_INLINE
    00958         const_iterator2 end2 () const {
    00959             return find2 (0, 0, size_);
    00960         }
    00961
    00962 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00963         class iterator2:
    00964             public container_reference<hermitian_matrix>,
    00965             public random_access_iterator_base<packed_random_access_iterator_tag,
    00966                                                iterator2, value_type> {
    00967         public:
    00968             typedef typename hermitian_matrix::value_type value_type;
    00969             typedef typename hermitian_matrix::difference_type difference_type;
    00970             typedef typename hermitian_matrix::true_reference reference;
    00971             typedef typename hermitian_matrix::pointer pointer;
    00972
    00973             typedef iterator1 dual_iterator_type;
    00974             typedef reverse_iterator1 dual_reverse_iterator_type;
    00975
    00976             // Construction and destruction
    00977             BOOST_UBLAS_INLINE
    00978             iterator2 ():
    00979                 container_reference<self_type> (), it1_ (), it2_ () {}
    00980             BOOST_UBLAS_INLINE
    00981             iterator2 (self_type &m, size_type it1, size_type it2):
    00982                 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
    00983
    00984             // Arithmetic
    00985             BOOST_UBLAS_INLINE
    00986             iterator2 &operator ++ () {
    00987                 ++ it2_;
    00988                 return *this;
    00989             }
    00990             BOOST_UBLAS_INLINE
    00991             iterator2 &operator -- () {
    00992                 -- it2_;
    00993                 return *this;
    00994             }
    00995             BOOST_UBLAS_INLINE
    00996             iterator2 &operator += (difference_type n) {
    00997                 it2_ += n;
    00998                 return *this;
    00999             }
    01000             BOOST_UBLAS_INLINE
    01001             iterator2 &operator -= (difference_type n) {
    01002                 it2_ -= n;
    01003                 return *this;
    01004             }
    01005             BOOST_UBLAS_INLINE
    01006             difference_type operator - (const iterator2 &it) const {
    01007                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01008                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    01009                 return it2_ - it.it2_;
    01010             }
    01011
    01012             // Dereference
    01013             BOOST_UBLAS_INLINE
    01014             reference operator * () const {
    01015                 return (*this) ().at_element (it1_, it2_);
    01016             }
    01017             BOOST_UBLAS_INLINE
    01018             reference operator [] (difference_type n) const {
    01019                 return *(*this + n);
    01020             }
    01021
    01022 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    01023             BOOST_UBLAS_INLINE
    01024 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01025             typename self_type::
    01026 #endif
    01027             iterator1 begin () const {
    01028                 return (*this) ().find1 (1, 0, it2_);
    01029             }
    01030             BOOST_UBLAS_INLINE
    01031 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01032             typename self_type::
    01033 #endif
    01034             iterator1 end () const {
    01035                 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
    01036             }
    01037             BOOST_UBLAS_INLINE
    01038 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01039             typename self_type::
    01040 #endif
    01041             reverse_iterator1 rbegin () const {
    01042                 return reverse_iterator1 (end ());
    01043             }
    01044             BOOST_UBLAS_INLINE
    01045 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01046             typename self_type::
    01047 #endif
    01048             reverse_iterator1 rend () const {
    01049                 return reverse_iterator1 (begin ());
    01050             }
    01051 #endif
    01052
    01053             // Indices
    01054             BOOST_UBLAS_INLINE
    01055             size_type index1 () const {
    01056                 return it1_;
    01057             }
    01058             BOOST_UBLAS_INLINE
    01059             size_type index2 () const {
    01060                 return it2_;
    01061             }
    01062
    01063             // Assignment
    01064             BOOST_UBLAS_INLINE
    01065             iterator2 &operator = (const iterator2 &it) {
    01066                 container_reference<self_type>::assign (&it ());
    01067                 it1_ = it.it1_;
    01068                 it2_ = it.it2_;
    01069                 return *this;
    01070             }
    01071
    01072             // Comparison
    01073             BOOST_UBLAS_INLINE
    01074             bool operator == (const iterator2 &it) const {
    01075                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01076                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    01077                 return it2_ == it.it2_;
    01078             }
    01079             BOOST_UBLAS_INLINE
    01080             bool operator < (const iterator2 &it) const {
    01081                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01082                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    01083                 return it2_ < it.it2_;
    01084             }
    01085
    01086         private:
    01087             size_type it1_;
    01088             size_type it2_;
    01089
    01090             friend class const_iterator2;
    01091         };
    01092 #endif
    01093
    01094         BOOST_UBLAS_INLINE
    01095         iterator2 begin2 () {
    01096             return find2 (0, 0, 0);
    01097         }
    01098         BOOST_UBLAS_INLINE
    01099         iterator2 end2 () {
    01100             return find2 (0, 0, size_);
    01101         }
    01102
    01103         // Reverse iterators
    01104
    01105         BOOST_UBLAS_INLINE
    01106         const_reverse_iterator1 rbegin1 () const {
    01107             return const_reverse_iterator1 (end1 ());
    01108         }
    01109         BOOST_UBLAS_INLINE
    01110         const_reverse_iterator1 rend1 () const {
    01111             return const_reverse_iterator1 (begin1 ());
    01112         }
    01113
    01114         BOOST_UBLAS_INLINE
    01115         reverse_iterator1 rbegin1 () {
    01116             return reverse_iterator1 (end1 ());
    01117         }
    01118         BOOST_UBLAS_INLINE
    01119         reverse_iterator1 rend1 () {
    01120             return reverse_iterator1 (begin1 ());
    01121         }
    01122
    01123         BOOST_UBLAS_INLINE
    01124         const_reverse_iterator2 rbegin2 () const {
    01125             return const_reverse_iterator2 (end2 ());
    01126         }
    01127         BOOST_UBLAS_INLINE
    01128         const_reverse_iterator2 rend2 () const {
    01129             return const_reverse_iterator2 (begin2 ());
    01130         }
    01131
    01132         BOOST_UBLAS_INLINE
    01133         reverse_iterator2 rbegin2 () {
    01134             return reverse_iterator2 (end2 ());
    01135         }
    01136         BOOST_UBLAS_INLINE
    01137         reverse_iterator2 rend2 () {
    01138             return reverse_iterator2 (begin2 ());
    01139         }
    01140
    01141     private:
    01142         size_type size_;
    01143         array_type data_;
    01144     };
    01145
    01155     template<class M, class TRI>
    01156     class hermitian_adaptor:
    01157         public matrix_expression<hermitian_adaptor<M, TRI> > {
    01158
    01159         typedef hermitian_adaptor<M, TRI> self_type;
    01160         typedef typename M::value_type &true_reference;
    01161     public:
    01162 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    01163         using matrix_expression<self_type>::operator ();
    01164 #endif
    01165         typedef const M const_matrix_type;
    01166         typedef M matrix_type;
    01167         typedef TRI triangular_type;
    01168         typedef typename M::size_type size_type;
    01169         typedef typename M::difference_type difference_type;
    01170         typedef typename M::value_type value_type;
    01171         typedef typename M::value_type const_reference;
    01172 #ifndef BOOST_UBLAS_STRICT_HERMITIAN
    01173         typedef typename boost::mpl::if_<boost::is_const<M>,
    01174                                           typename M::value_type,
    01175                                           typename M::reference>::type reference;
    01176 #else
    01177         typedef typename boost::mpl::if_<boost::is_const<M>,
    01178                                           typename M::value_type,
    01179                                           hermitian_matrix_element<self_type> >::type reference;
    01180 #endif
    01181         typedef typename boost::mpl::if_<boost::is_const<M>,
    01182                                           typename M::const_closure_type,
    01183                                           typename M::closure_type>::type matrix_closure_type;
    01184         typedef const self_type const_closure_type;
    01185         typedef self_type closure_type;
    01186         // Replaced by _temporary_traits to avoid type requirements on M
    01187         //typedef typename M::vector_temporary_type vector_temporary_type;
    01188         //typedef typename M::matrix_temporary_type matrix_temporary_type;
    01189         typedef typename storage_restrict_traits<typename M::storage_category,
    01190                                                  packed_proxy_tag>::storage_category storage_category;
    01191         typedef typename M::orientation_category orientation_category;
    01192
    01193         // Construction and destruction
    01194         BOOST_UBLAS_INLINE
    01195         hermitian_adaptor (matrix_type &data):
    01196             matrix_expression<self_type> (),
    01197             data_ (data) {
    01198             BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
    01199         }
    01200         BOOST_UBLAS_INLINE
    01201         hermitian_adaptor (const hermitian_adaptor &m):
    01202             matrix_expression<self_type> (),
    01203             data_ (m.data_) {
    01204             BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
    01205         }
    01206
    01207         // Accessors
    01208         BOOST_UBLAS_INLINE
    01209         size_type size1 () const {
    01210             return data_.size1 ();
    01211         }
    01212         BOOST_UBLAS_INLINE
    01213         size_type size2 () const {
    01214             return data_.size2 ();
    01215         }
    01216
    01217         // Storage accessors
    01218         BOOST_UBLAS_INLINE
    01219         const matrix_closure_type &data () const {
    01220             return data_;
    01221         }
    01222         BOOST_UBLAS_INLINE
    01223         matrix_closure_type &data () {
    01224             return data_;
    01225         }
    01226
    01227         // Element access
    01228 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
    01229         BOOST_UBLAS_INLINE
    01230         const_reference operator () (size_type i, size_type j) const {
    01231             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
    01232             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
    01233             // if (i == j)
    01234             //     return type_traits<value_type>::real (data () (i, i));
    01235             // else
    01236             if (triangular_type::other (i, j))
    01237                 return data () (i, j);
    01238             else
    01239                 return type_traits<value_type>::conj (data () (j, i));
    01240         }
    01241         BOOST_UBLAS_INLINE
    01242         reference operator () (size_type i, size_type j) {
    01243             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
    01244             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
    01245 #ifndef BOOST_UBLAS_STRICT_HERMITIAN
    01246             if (triangular_type::other (i, j))
    01247                 return data () (i, j);
    01248             else {
    01249                 external_logic ().raise ();
    01250                 return conj_ = type_traits<value_type>::conj (data () (j, i));
    01251             }
    01252 #else
    01253             if (triangular_type::other (i, j))
    01254                 return reference (*this, i, j, data () (i, j));
    01255             else
    01256                 return reference (*this, i, j, type_traits<value_type>::conj (data () (j, i)));
    01257 #endif
    01258         }
    01259         BOOST_UBLAS_INLINE
    01260         true_reference insert_element (size_type i, size_type j, value_type t) {
    01261             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
    01262             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
    01263             // if (i == j)
    01264             //     data () (i, i) = type_traits<value_type>::real (t);
    01265             // else
    01266             if (triangular_type::other (i, j))
    01267                 return data () (i, j) = t;
    01268             else
    01269                 return data () (j, i) = type_traits<value_type>::conj (t);
    01270         }
    01271 #else
    01272         BOOST_UBLAS_INLINE
    01273         reference operator () (size_type i, size_type j) {
    01274             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
    01275             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
    01276 #ifndef BOOST_UBLAS_STRICT_HERMITIAN
    01277             if (triangular_type::other (i, j))
    01278                 return data () (i, j);
    01279             else {
    01280                 external_logic ().raise ();
    01281                 return conj_ = type_traits<value_type>::conj (data () (j, i));
    01282             }
    01283 #else
    01284             if (triangular_type::other (i, j))
    01285                 return reference (*this, i, j, data () (i, j));
    01286             else
    01287                 return reference (*this, i, j, type_traits<value_type>::conj (data () (j, i)));
    01288 #endif
    01289         }
    01290         BOOST_UBLAS_INLINE
    01291         true_reference insert_element (size_type i, size_type j, value_type t) {
    01292             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
    01293             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
    01294             // if (i == j)
    01295             //     data () (i, i) = type_traits<value_type>::real (t);
    01296             // else
    01297             if (triangular_type::other (i, j))
    01298                 return data () (i, j) = t;
    01299             else
    01300                 return data () (j, i) = type_traits<value_type>::conj (t);
    01301         }
    01302 #endif
    01303
    01304         // Assignment
    01305         BOOST_UBLAS_INLINE
    01306         hermitian_adaptor &operator = (const hermitian_adaptor &m) {
    01307             matrix_assign<scalar_assign, triangular_type> (*this, m);
    01308             return *this;
    01309         }
    01310         BOOST_UBLAS_INLINE
    01311         hermitian_adaptor &assign_temporary (hermitian_adaptor &m) {
    01312             *this = m;
    01313             return *this;
    01314         }
    01315         template<class AE>
    01316         BOOST_UBLAS_INLINE
    01317         hermitian_adaptor &operator = (const matrix_expression<AE> &ae) {
    01318             matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae));
    01319             return *this;
    01320         }
    01321         template<class AE>
    01322         BOOST_UBLAS_INLINE
    01323         hermitian_adaptor &assign (const matrix_expression<AE> &ae) {
    01324             matrix_assign<scalar_assign, triangular_type> (*this, ae);
    01325             return *this;
    01326         }
    01327         template<class AE>
    01328         BOOST_UBLAS_INLINE
    01329         hermitian_adaptor& operator += (const matrix_expression<AE> &ae) {
    01330             matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae));
    01331             return *this;
    01332         }
    01333         template<class AE>
    01334         BOOST_UBLAS_INLINE
    01335         hermitian_adaptor &plus_assign (const matrix_expression<AE> &ae) {
    01336             matrix_assign<scalar_plus_assign, triangular_type> (*this, ae);
    01337             return *this;
    01338         }
    01339         template<class AE>
    01340         BOOST_UBLAS_INLINE
    01341         hermitian_adaptor& operator -= (const matrix_expression<AE> &ae) {
    01342             matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae));
    01343             return *this;
    01344         }
    01345         template<class AE>
    01346         BOOST_UBLAS_INLINE
    01347         hermitian_adaptor &minus_assign (const matrix_expression<AE> &ae) {
    01348             matrix_assign<scalar_minus_assign, triangular_type> (*this, ae);
    01349             return *this;
    01350         }
    01351         template<class AT>
    01352         BOOST_UBLAS_INLINE
    01353         hermitian_adaptor& operator *= (const AT &at) {
    01354             // Multiplication is only allowed for real scalars,
    01355             // otherwise the resulting matrix isn't hermitian.
    01356             // Thanks to Peter Schmitteckert for spotting this.
    01357             BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
    01358             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
    01359             return *this;
    01360         }
    01361         template<class AT>
    01362         BOOST_UBLAS_INLINE
    01363         hermitian_adaptor& operator /= (const AT &at) {
    01364             // Multiplication is only allowed for real scalars,
    01365             // otherwise the resulting matrix isn't hermitian.
    01366             // Thanks to Peter Schmitteckert for spotting this.
    01367             BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
    01368             matrix_assign_scalar<scalar_divides_assign> (*this, at);
    01369             return *this;
    01370         }
    01371
    01372         // Closure comparison
    01373         BOOST_UBLAS_INLINE
    01374         bool same_closure (const hermitian_adaptor &ha) const {
    01375             return (*this).data ().same_closure (ha.data ());
    01376         }
    01377
    01378         // Swapping
    01379         BOOST_UBLAS_INLINE
    01380         void swap (hermitian_adaptor &m) {
    01381             if (this != &m)
    01382                 matrix_swap<scalar_swap, triangular_type> (*this, m);
    01383         }
    01384         BOOST_UBLAS_INLINE
    01385         friend void swap (hermitian_adaptor &m1, hermitian_adaptor &m2) {
    01386             m1.swap (m2);
    01387         }
    01388
    01389         // Iterator types
    01390     private:
    01391         // Use matrix iterator
    01392         typedef typename M::const_iterator1 const_subiterator1_type;
    01393         typedef typename boost::mpl::if_<boost::is_const<M>,
    01394                                           typename M::const_iterator1,
    01395                                           typename M::iterator1>::type subiterator1_type;
    01396         typedef typename M::const_iterator2 const_subiterator2_type;
    01397         typedef typename boost::mpl::if_<boost::is_const<M>,
    01398                                           typename M::const_iterator2,
    01399                                           typename M::iterator2>::type subiterator2_type;
    01400
    01401     public:
    01402 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01403         typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
    01404         typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
    01405         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
    01406         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
    01407 #else
    01408         class const_iterator1;
    01409         class iterator1;
    01410         class const_iterator2;
    01411         class iterator2;
    01412 #endif
    01413         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    01414         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
    01415         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    01416         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
    01417
    01418         // Element lookup
    01419         BOOST_UBLAS_INLINE
    01420         const_iterator1 find1 (int rank, size_type i, size_type j) const {
    01421             if (triangular_type::other (i, j)) {
    01422                 if (triangular_type::other (size1 (), j)) {
    01423                     return const_iterator1 (*this, 0, 0,
    01424                                             data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j),
    01425                                             data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ()));
    01426                 } else {
    01427                     return const_iterator1 (*this, 0, 1,
    01428                                             data ().find1 (rank, i, j), data ().find1 (rank, j, j),
    01429                                             data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ()));
    01430                 }
    01431             } else {
    01432                 if (triangular_type::other (size1 (), j)) {
    01433                     return const_iterator1 (*this, 1, 0,
    01434                                             data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j),
    01435                                             data ().find2 (rank, j, i), data ().find2 (rank, j, j));
    01436                 } else {
    01437                     return const_iterator1 (*this, 1, 1,
    01438                                             data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()),
    01439                                             data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ()));
    01440                 }
    01441             }
    01442         }
    01443         BOOST_UBLAS_INLINE
    01444         iterator1 find1 (int rank, size_type i, size_type j) {
    01445             if (rank == 1)
    01446                 i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
    01447             if (rank == 0)
    01448                 i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
    01449             return iterator1 (*this, data ().find1 (rank, i, j));
    01450         }
    01451         BOOST_UBLAS_INLINE
    01452         const_iterator2 find2 (int rank, size_type i, size_type j) const {
    01453             if (triangular_type::other (i, j)) {
    01454                 if (triangular_type::other (i, size2 ())) {
    01455                     return const_iterator2 (*this, 1, 1,
    01456                                             data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()),
    01457                                             data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ()));
    01458                 } else {
    01459                     return const_iterator2 (*this, 1, 0,
    01460                                             data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i),
    01461                                             data ().find2 (rank, i, j), data ().find2 (rank, i, i));
    01462                 }
    01463             } else {
    01464                 if (triangular_type::other (i, size2 ())) {
    01465                     return const_iterator2 (*this, 0, 1,
    01466                                             data ().find1 (rank, j, i), data ().find1 (rank, i, i),
    01467                                             data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ()));
    01468                 } else {
    01469                     return const_iterator2 (*this, 0, 0,
    01470                                             data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i),
    01471                                             data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ()));
    01472                 }
    01473             }
    01474         }
    01475         BOOST_UBLAS_INLINE
    01476         iterator2 find2 (int rank, size_type i, size_type j) {
    01477             if (rank == 1)
    01478                 j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
    01479             if (rank == 0)
    01480                 j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
    01481             return iterator2 (*this, data ().find2 (rank, i, j));
    01482         }
    01483
    01484         // Iterators simply are indices.
    01485
    01486 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01487         class const_iterator1:
    01488             public container_const_reference<hermitian_adaptor>,
    01489             public random_access_iterator_base<typename iterator_restrict_traits<
    01490                                                    typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
    01491                                                const_iterator1, value_type> {
    01492         public:
    01493             typedef typename const_subiterator1_type::value_type value_type;
    01494             typedef typename const_subiterator1_type::difference_type difference_type;
    01495             // FIXME no better way to not return the address of a temporary?
    01496             // typedef typename const_subiterator1_type::reference reference;
    01497             typedef typename const_subiterator1_type::value_type reference;
    01498             typedef typename const_subiterator1_type::pointer pointer;
    01499
    01500             typedef const_iterator2 dual_iterator_type;
    01501             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    01502
    01503             // Construction and destruction
    01504             BOOST_UBLAS_INLINE
    01505             const_iterator1 ():
    01506                 container_const_reference<self_type> (),
    01507                 begin_ (-1), end_ (-1), current_ (-1),
    01508                 it1_begin_ (), it1_end_ (), it1_ (),
    01509                 it2_begin_ (), it2_end_ (), it2_ () {}
    01510             BOOST_UBLAS_INLINE
    01511             const_iterator1 (const self_type &m, int begin, int end,
    01512                              const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
    01513                              const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
    01514                 container_const_reference<self_type> (m),
    01515                 begin_ (begin), end_ (end), current_ (begin),
    01516                 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
    01517                 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
    01518                 if (current_ == 0 && it1_ == it1_end_)
    01519                     current_ = 1;
    01520                 if (current_ == 1 && it2_ == it2_end_)
    01521                     current_ = 0;
    01522                 if ((current_ == 0 && it1_ == it1_end_) ||
    01523                     (current_ == 1 && it2_ == it2_end_))
    01524                     current_ = end_;
    01525                 BOOST_UBLAS_CHECK (current_ == end_ ||
    01526                                    (current_ == 0 && it1_ != it1_end_) ||
    01527                                    (current_ == 1 && it2_ != it2_end_), internal_logic ());
    01528             }
    01529             // FIXME cannot compile
    01530             //  iterator1 does not have these members!
    01531             BOOST_UBLAS_INLINE
    01532             const_iterator1 (const iterator1 &it):
    01533                 container_const_reference<self_type> (it ()),
    01534                 begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
    01535                 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
    01536                 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
    01537                 BOOST_UBLAS_CHECK (current_ == end_ ||
    01538                                    (current_ == 0 && it1_ != it1_end_) ||
    01539                                    (current_ == 1 && it2_ != it2_end_), internal_logic ());
    01540             }
    01541
    01542             // Arithmetic
    01543             BOOST_UBLAS_INLINE
    01544             const_iterator1 &operator ++ () {
    01545                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    01546                 if (current_ == 0) {
    01547                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
    01548                     ++ it1_;
    01549                     if (it1_ == it1_end_ && end_ == 1) {
    01550                         it2_ = it2_begin_;
    01551                         current_ = 1;
    01552                     }
    01553                 } else /* if (current_ == 1) */ {
    01554                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
    01555                     ++ it2_;
    01556                     if (it2_ == it2_end_ && end_ == 0) {
    01557                         it1_ = it1_begin_;
    01558                         current_ = 0;
    01559                     }
    01560                 }
    01561                 return *this;
    01562             }
    01563             BOOST_UBLAS_INLINE
    01564             const_iterator1 &operator -- () {
    01565                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    01566                 if (current_ == 0) {
    01567                     if (it1_ == it1_begin_ && begin_ == 1) {
    01568                         it2_ = it2_end_;
    01569                         BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
    01570                         -- it2_;
    01571                         current_ = 1;
    01572                     } else {
    01573                         -- it1_;
    01574                     }
    01575                 } else /* if (current_ == 1) */ {
    01576                     if (it2_ == it2_begin_ && begin_ == 0) {
    01577                         it1_ = it1_end_;
    01578                         BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
    01579                         -- it1_;
    01580                         current_ = 0;
    01581                     } else {
    01582                         -- it2_;
    01583                     }
    01584                 }
    01585                 return *this;
    01586             }
    01587             BOOST_UBLAS_INLINE
    01588             const_iterator1 &operator += (difference_type n) {
    01589                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    01590                 if (current_ == 0) {
    01591                     size_type d = (std::min) (n, it1_end_ - it1_);
    01592                     it1_ += d;
    01593                     n -= d;
    01594                     if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
    01595                         BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
    01596                         d = (std::min) (n, it2_end_ - it2_begin_);
    01597                         it2_ = it2_begin_ + d;
    01598                         n -= d;
    01599                         current_ = 1;
    01600                     }
    01601                 } else /* if (current_ == 1) */ {
    01602                     size_type d = (std::min) (n, it2_end_ - it2_);
    01603                     it2_ += d;
    01604                     n -= d;
    01605                     if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
    01606                         BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
    01607                         d = (std::min) (n, it1_end_ - it1_begin_);
    01608                         it1_ = it1_begin_ + d;
    01609                         n -= d;
    01610                         current_ = 0;
    01611                     }
    01612                 }
    01613                 BOOST_UBLAS_CHECK (n == 0, external_logic ());
    01614                 return *this;
    01615             }
    01616             BOOST_UBLAS_INLINE
    01617             const_iterator1 &operator -= (difference_type n) {
    01618                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    01619                 if (current_ == 0) {
    01620                     size_type d = (std::min) (n, it1_ - it1_begin_);
    01621                     it1_ -= d;
    01622                     n -= d;
    01623                     if (n > 0) {
    01624                         BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
    01625                         d = (std::min) (n, it2_end_ - it2_begin_);
    01626                         it2_ = it2_end_ - d;
    01627                         n -= d;
    01628                         current_ = 1;
    01629                     }
    01630                 } else /* if (current_ == 1) */ {
    01631                     size_type d = (std::min) (n, it2_ - it2_begin_);
    01632                     it2_ -= d;
    01633                     n -= d;
    01634                     if (n > 0) {
    01635                         BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
    01636                         d = (std::min) (n, it1_end_ - it1_begin_);
    01637                         it1_ = it1_end_ - d;
    01638                         n -= d;
    01639                         current_ = 0;
    01640                     }
    01641                 }
    01642                 BOOST_UBLAS_CHECK (n == 0, external_logic ());
    01643                 return *this;
    01644             }
    01645             BOOST_UBLAS_INLINE
    01646             difference_type operator - (const const_iterator1 &it) const {
    01647                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01648                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    01649                 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
    01650                 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
    01651                 if (current_ == 0 && it.current_ == 0) {
    01652                     return it1_ - it.it1_;
    01653                 } else if (current_ == 0 && it.current_ == 1) {
    01654                     if (end_ == 1 && it.end_ == 1) {
    01655                         return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
    01656                     } else /* if (end_ == 0 && it.end_ == 0) */ {
    01657                         return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
    01658                     }
    01659
    01660                 } else if (current_ == 1 && it.current_ == 0) {
    01661                     if (end_ == 1 && it.end_ == 1) {
    01662                         return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
    01663                     } else /* if (end_ == 0 && it.end_ == 0) */ {
    01664                         return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
    01665                     }
    01666                 } else /* if (current_ == 1 && it.current_ == 1) */ {
    01667                     return it2_ - it.it2_;
    01668                 }
    01669             }
    01670
    01671             // Dereference
    01672             BOOST_UBLAS_INLINE
    01673             const_reference operator * () const {
    01674                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    01675                 if (current_ == 0) {
    01676                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
    01677                     if (triangular_type::other (index1 (), index2 ()))
    01678                         return *it1_;
    01679                     else
    01680                         return type_traits<value_type>::conj (*it1_);
    01681                 } else /* if (current_ == 1) */ {
    01682                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
    01683                     if (triangular_type::other (index1 (), index2 ()))
    01684                         return *it2_;
    01685                     else
    01686                         return type_traits<value_type>::conj (*it2_);
    01687                 }
    01688             }
    01689             BOOST_UBLAS_INLINE
    01690             const_reference operator [] (difference_type n) const {
    01691                 return *(*this + n);
    01692             }
    01693
    01694 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    01695             BOOST_UBLAS_INLINE
    01696 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01697             typename self_type::
    01698 #endif
    01699             const_iterator2 begin () const {
    01700                 return (*this) ().find2 (1, index1 (), 0);
    01701             }
    01702             BOOST_UBLAS_INLINE
    01703 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01704             typename self_type::
    01705 #endif
    01706             const_iterator2 end () const {
    01707                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
    01708             }
    01709             BOOST_UBLAS_INLINE
    01710 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01711             typename self_type::
    01712 #endif
    01713             const_reverse_iterator2 rbegin () const {
    01714                 return const_reverse_iterator2 (end ());
    01715             }
    01716             BOOST_UBLAS_INLINE
    01717 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01718             typename self_type::
    01719 #endif
    01720             const_reverse_iterator2 rend () const {
    01721                 return const_reverse_iterator2 (begin ());
    01722             }
    01723 #endif
    01724
    01725             // Indices
    01726             BOOST_UBLAS_INLINE
    01727             size_type index1 () const {
    01728                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    01729                 if (current_ == 0) {
    01730                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
    01731                     return it1_.index1 ();
    01732                 } else /* if (current_ == 1) */ {
    01733                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
    01734                     return it2_.index2 ();
    01735                 }
    01736             }
    01737             BOOST_UBLAS_INLINE
    01738             size_type index2 () const {
    01739                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    01740                 if (current_ == 0) {
    01741                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
    01742                     return it1_.index2 ();
    01743                 } else /* if (current_ == 1) */ {
    01744                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
    01745                     return it2_.index1 ();
    01746                 }
    01747             }
    01748
    01749             // Assignment
    01750             BOOST_UBLAS_INLINE
    01751             const_iterator1 &operator = (const const_iterator1 &it) {
    01752                 container_const_reference<self_type>::assign (&it ());
    01753                 begin_ = it.begin_;
    01754                 end_ = it.end_;
    01755                 current_ = it.current_;
    01756                 it1_begin_ = it.it1_begin_;
    01757                 it1_end_ = it.it1_end_;
    01758                 it1_ = it.it1_;
    01759                 it2_begin_ = it.it2_begin_;
    01760                 it2_end_ = it.it2_end_;
    01761                 it2_ = it.it2_;
    01762                 return *this;
    01763             }
    01764
    01765             // Comparison
    01766             BOOST_UBLAS_INLINE
    01767             bool operator == (const const_iterator1 &it) const {
    01768                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01769                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    01770                 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
    01771                 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
    01772                 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
    01773                        (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
    01774             }
    01775             BOOST_UBLAS_INLINE
    01776             bool operator < (const const_iterator1 &it) const {
    01777                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01778                 return it - *this > 0;
    01779             }
    01780
    01781         private:
    01782             int begin_;
    01783             int end_;
    01784             int current_;
    01785             const_subiterator1_type it1_begin_;
    01786             const_subiterator1_type it1_end_;
    01787             const_subiterator1_type it1_;
    01788             const_subiterator2_type it2_begin_;
    01789             const_subiterator2_type it2_end_;
    01790             const_subiterator2_type it2_;
    01791         };
    01792 #endif
    01793
    01794         BOOST_UBLAS_INLINE
    01795         const_iterator1 begin1 () const {
    01796             return find1 (0, 0, 0);
    01797         }
    01798         BOOST_UBLAS_INLINE
    01799         const_iterator1 end1 () const {
    01800             return find1 (0, size1 (), 0);
    01801         }
    01802
    01803 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01804         class iterator1:
    01805             public container_reference<hermitian_adaptor>,
    01806             public random_access_iterator_base<typename iterator_restrict_traits<
    01807                                                    typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
    01808                                                iterator1, value_type> {
    01809         public:
    01810             typedef typename subiterator1_type::value_type value_type;
    01811             typedef typename subiterator1_type::difference_type difference_type;
    01812             typedef typename subiterator1_type::reference reference;
    01813             typedef typename subiterator1_type::pointer pointer;
    01814
    01815             typedef iterator2 dual_iterator_type;
    01816             typedef reverse_iterator2 dual_reverse_iterator_type;
    01817
    01818             // Construction and destruction
    01819             BOOST_UBLAS_INLINE
    01820             iterator1 ():
    01821                 container_reference<self_type> (), it1_ () {}
    01822             BOOST_UBLAS_INLINE
    01823             iterator1 (self_type &m, const subiterator1_type &it1):
    01824                 container_reference<self_type> (m), it1_ (it1) {}
    01825
    01826             // Arithmetic
    01827             BOOST_UBLAS_INLINE
    01828             iterator1 &operator ++ () {
    01829                 ++ it1_;
    01830                 return *this;
    01831             }
    01832             BOOST_UBLAS_INLINE
    01833             iterator1 &operator -- () {
    01834                 -- it1_;
    01835                 return *this;
    01836             }
    01837             BOOST_UBLAS_INLINE
    01838             iterator1 &operator += (difference_type n) {
    01839                 it1_ += n;
    01840                 return *this;
    01841             }
    01842             BOOST_UBLAS_INLINE
    01843             iterator1 &operator -= (difference_type n) {
    01844                 it1_ -= n;
    01845                 return *this;
    01846             }
    01847             BOOST_UBLAS_INLINE
    01848             difference_type operator - (const iterator1 &it) const {
    01849                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01850                 return it1_ - it.it1_;
    01851             }
    01852
    01853             // Dereference
    01854             BOOST_UBLAS_INLINE
    01855             reference operator * () const {
    01856                 return *it1_;
    01857             }
    01858             BOOST_UBLAS_INLINE
    01859             reference operator [] (difference_type n) const {
    01860                 return *(*this + n);
    01861             }
    01862
    01863 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    01864             BOOST_UBLAS_INLINE
    01865 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01866             typename self_type::
    01867 #endif
    01868             iterator2 begin () const {
    01869                 return (*this) ().find2 (1, index1 (), 0);
    01870             }
    01871             BOOST_UBLAS_INLINE
    01872 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01873             typename self_type::
    01874 #endif
    01875             iterator2 end () const {
    01876                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
    01877             }
    01878             BOOST_UBLAS_INLINE
    01879 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01880             typename self_type::
    01881 #endif
    01882             reverse_iterator2 rbegin () const {
    01883                 return reverse_iterator2 (end ());
    01884             }
    01885             BOOST_UBLAS_INLINE
    01886 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01887             typename self_type::
    01888 #endif
    01889             reverse_iterator2 rend () const {
    01890                 return reverse_iterator2 (begin ());
    01891             }
    01892 #endif
    01893
    01894             // Indices
    01895             BOOST_UBLAS_INLINE
    01896             size_type index1 () const {
    01897                 return it1_.index1 ();
    01898             }
    01899             BOOST_UBLAS_INLINE
    01900             size_type index2 () const {
    01901                 return it1_.index2 ();
    01902             }
    01903
    01904             // Assignment
    01905             BOOST_UBLAS_INLINE
    01906             iterator1 &operator = (const iterator1 &it) {
    01907                 container_reference<self_type>::assign (&it ());
    01908                 it1_ = it.it1_;
    01909                 return *this;
    01910             }
    01911
    01912             // Comparison
    01913             BOOST_UBLAS_INLINE
    01914             bool operator == (const iterator1 &it) const {
    01915                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01916                 return it1_ == it.it1_;
    01917             }
    01918             BOOST_UBLAS_INLINE
    01919             bool operator < (const iterator1 &it) const {
    01920                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01921                 return it1_ < it.it1_;
    01922             }
    01923
    01924         private:
    01925             subiterator1_type it1_;
    01926
    01927             friend class const_iterator1;
    01928         };
    01929 #endif
    01930
    01931         BOOST_UBLAS_INLINE
    01932         iterator1 begin1 () {
    01933             return find1 (0, 0, 0);
    01934         }
    01935         BOOST_UBLAS_INLINE
    01936         iterator1 end1 () {
    01937             return find1 (0, size1 (), 0);
    01938         }
    01939
    01940 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01941         class const_iterator2:
    01942             public container_const_reference<hermitian_adaptor>,
    01943             public random_access_iterator_base<typename iterator_restrict_traits<
    01944             typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
    01945                                                const_iterator2, value_type> {
    01946         public:
    01947             typedef typename const_subiterator2_type::value_type value_type;
    01948             typedef typename const_subiterator2_type::difference_type difference_type;
    01949             // FIXME no better way to not return the address of a temporary?
    01950             // typedef typename const_subiterator2_type::reference reference;
    01951             typedef typename const_subiterator2_type::value_type reference;
    01952             typedef typename const_subiterator2_type::pointer pointer;
    01953
    01954             typedef const_iterator1 dual_iterator_type;
    01955             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    01956
    01957             // Construction and destruction
    01958             BOOST_UBLAS_INLINE
    01959             const_iterator2 ():
    01960                 container_const_reference<self_type> (),
    01961                 begin_ (-1), end_ (-1), current_ (-1),
    01962                 it1_begin_ (), it1_end_ (), it1_ (),
    01963                 it2_begin_ (), it2_end_ (), it2_ () {}
    01964             BOOST_UBLAS_INLINE
    01965             const_iterator2 (const self_type &m, int begin, int end,
    01966                              const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
    01967                              const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
    01968                 container_const_reference<self_type> (m),
    01969                 begin_ (begin), end_ (end), current_ (begin),
    01970                 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
    01971                 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
    01972                 if (current_ == 0 && it1_ == it1_end_)
    01973                     current_ = 1;
    01974                 if (current_ == 1 && it2_ == it2_end_)
    01975                     current_ = 0;
    01976                 if ((current_ == 0 && it1_ == it1_end_) ||
    01977                     (current_ == 1 && it2_ == it2_end_))
    01978                     current_ = end_;
    01979                 BOOST_UBLAS_CHECK (current_ == end_ ||
    01980                                    (current_ == 0 && it1_ != it1_end_) ||
    01981                                    (current_ == 1 && it2_ != it2_end_), internal_logic ());
    01982             }
    01983             // FIXME cannot compiler
    01984             //  iterator2 does not have these members!
    01985             BOOST_UBLAS_INLINE
    01986             const_iterator2 (const iterator2 &it):
    01987                 container_const_reference<self_type> (it ()),
    01988                 begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
    01989                 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
    01990                 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
    01991                 BOOST_UBLAS_CHECK (current_ == end_ ||
    01992                                    (current_ == 0 && it1_ != it1_end_) ||
    01993                                    (current_ == 1 && it2_ != it2_end_), internal_logic ());
    01994             }
    01995
    01996             // Arithmetic
    01997             BOOST_UBLAS_INLINE
    01998             const_iterator2 &operator ++ () {
    01999                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    02000                 if (current_ == 0) {
    02001                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
    02002                     ++ it1_;
    02003                     if (it1_ == it1_end_ && end_ == 1) {
    02004                         it2_ = it2_begin_;
    02005                         current_ = 1;
    02006                     }
    02007                 } else /* if (current_ == 1) */ {
    02008                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
    02009                     ++ it2_;
    02010                     if (it2_ == it2_end_ && end_ == 0) {
    02011                         it1_ = it1_begin_;
    02012                         current_ = 0;
    02013                     }
    02014                 }
    02015                 return *this;
    02016             }
    02017             BOOST_UBLAS_INLINE
    02018             const_iterator2 &operator -- () {
    02019                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    02020                 if (current_ == 0) {
    02021                     if (it1_ == it1_begin_ && begin_ == 1) {
    02022                         it2_ = it2_end_;
    02023                         BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
    02024                         -- it2_;
    02025                         current_ = 1;
    02026                     } else {
    02027                         -- it1_;
    02028                     }
    02029                 } else /* if (current_ == 1) */ {
    02030                     if (it2_ == it2_begin_ && begin_ == 0) {
    02031                         it1_ = it1_end_;
    02032                         BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
    02033                         -- it1_;
    02034                         current_ = 0;
    02035                     } else {
    02036                         -- it2_;
    02037                     }
    02038                 }
    02039                 return *this;
    02040             }
    02041             BOOST_UBLAS_INLINE
    02042             const_iterator2 &operator += (difference_type n) {
    02043                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    02044                 if (current_ == 0) {
    02045                     size_type d = (std::min) (n, it1_end_ - it1_);
    02046                     it1_ += d;
    02047                     n -= d;
    02048                     if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
    02049                         BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
    02050                         d = (std::min) (n, it2_end_ - it2_begin_);
    02051                         it2_ = it2_begin_ + d;
    02052                         n -= d;
    02053                         current_ = 1;
    02054                     }
    02055                 } else /* if (current_ == 1) */ {
    02056                     size_type d = (std::min) (n, it2_end_ - it2_);
    02057                     it2_ += d;
    02058                     n -= d;
    02059                     if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
    02060                         BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
    02061                         d = (std::min) (n, it1_end_ - it1_begin_);
    02062                         it1_ = it1_begin_ + d;
    02063                         n -= d;
    02064                         current_ = 0;
    02065                     }
    02066                 }
    02067                 BOOST_UBLAS_CHECK (n == 0, external_logic ());
    02068                 return *this;
    02069             }
    02070             BOOST_UBLAS_INLINE
    02071             const_iterator2 &operator -= (difference_type n) {
    02072                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    02073                 if (current_ == 0) {
    02074                     size_type d = (std::min) (n, it1_ - it1_begin_);
    02075                     it1_ -= d;
    02076                     n -= d;
    02077                     if (n > 0) {
    02078                         BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
    02079                         d = (std::min) (n, it2_end_ - it2_begin_);
    02080                         it2_ = it2_end_ - d;
    02081                         n -= d;
    02082                         current_ = 1;
    02083                     }
    02084                 } else /* if (current_ == 1) */ {
    02085                     size_type d = (std::min) (n, it2_ - it2_begin_);
    02086                     it2_ -= d;
    02087                     n -= d;
    02088                     if (n > 0) {
    02089                         BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
    02090                         d = (std::min) (n, it1_end_ - it1_begin_);
    02091                         it1_ = it1_end_ - d;
    02092                         n -= d;
    02093                         current_ = 0;
    02094                     }
    02095                 }
    02096                 BOOST_UBLAS_CHECK (n == 0, external_logic ());
    02097                 return *this;
    02098             }
    02099             BOOST_UBLAS_INLINE
    02100             difference_type operator - (const const_iterator2 &it) const {
    02101                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    02102                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    02103                 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
    02104                 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
    02105                 if (current_ == 0 && it.current_ == 0) {
    02106                     return it1_ - it.it1_;
    02107                 } else if (current_ == 0 && it.current_ == 1) {
    02108                     if (end_ == 1 && it.end_ == 1) {
    02109                         return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
    02110                     } else /* if (end_ == 0 && it.end_ == 0) */ {
    02111                         return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
    02112                     }
    02113
    02114                 } else if (current_ == 1 && it.current_ == 0) {
    02115                     if (end_ == 1 && it.end_ == 1) {
    02116                         return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
    02117                     } else /* if (end_ == 0 && it.end_ == 0) */ {
    02118                         return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
    02119                     }
    02120                 } else /* if (current_ == 1 && it.current_ == 1) */ {
    02121                     return it2_ - it.it2_;
    02122                 }
    02123             }
    02124
    02125             // Dereference
    02126             BOOST_UBLAS_INLINE
    02127             const_reference operator * () const {
    02128                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    02129                 if (current_ == 0) {
    02130                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
    02131                     if (triangular_type::other (index1 (), index2 ()))
    02132                         return *it1_;
    02133                     else
    02134                         return type_traits<value_type>::conj (*it1_);
    02135                 } else /* if (current_ == 1) */ {
    02136                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
    02137                     if (triangular_type::other (index1 (), index2 ()))
    02138                         return *it2_;
    02139                     else
    02140                         return type_traits<value_type>::conj (*it2_);
    02141                 }
    02142             }
    02143             BOOST_UBLAS_INLINE
    02144             const_reference operator [] (difference_type n) const {
    02145                 return *(*this + n);
    02146             }
    02147
    02148 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02149             BOOST_UBLAS_INLINE
    02150 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02151             typename self_type::
    02152 #endif
    02153             const_iterator1 begin () const {
    02154                 return (*this) ().find1 (1, 0, index2 ());
    02155             }
    02156             BOOST_UBLAS_INLINE
    02157 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02158             typename self_type::
    02159 #endif
    02160             const_iterator1 end () const {
    02161                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
    02162             }
    02163             BOOST_UBLAS_INLINE
    02164 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02165             typename self_type::
    02166 #endif
    02167             const_reverse_iterator1 rbegin () const {
    02168                 return const_reverse_iterator1 (end ());
    02169             }
    02170             BOOST_UBLAS_INLINE
    02171 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02172             typename self_type::
    02173 #endif
    02174             const_reverse_iterator1 rend () const {
    02175                 return const_reverse_iterator1 (begin ());
    02176             }
    02177 #endif
    02178
    02179             // Indices
    02180             BOOST_UBLAS_INLINE
    02181             size_type index1 () const {
    02182                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    02183                 if (current_ == 0) {
    02184                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
    02185                     return it1_.index2 ();
    02186                 } else /* if (current_ == 1) */ {
    02187                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
    02188                     return it2_.index1 ();
    02189                 }
    02190             }
    02191             BOOST_UBLAS_INLINE
    02192             size_type index2 () const {
    02193                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    02194                 if (current_ == 0) {
    02195                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
    02196                     return it1_.index1 ();
    02197                 } else /* if (current_ == 1) */ {
    02198                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
    02199                     return it2_.index2 ();
    02200                 }
    02201             }
    02202
    02203             // Assignment
    02204             BOOST_UBLAS_INLINE
    02205             const_iterator2 &operator = (const const_iterator2 &it) {
    02206                 container_const_reference<self_type>::assign (&it ());
    02207                 begin_ = it.begin_;
    02208                 end_ = it.end_;
    02209                 current_ = it.current_;
    02210                 it1_begin_ = it.it1_begin_;
    02211                 it1_end_ = it.it1_end_;
    02212                 it1_ = it.it1_;
    02213                 it2_begin_ = it.it2_begin_;
    02214                 it2_end_ = it.it2_end_;
    02215                 it2_ = it.it2_;
    02216                 return *this;
    02217             }
    02218
    02219             // Comparison
    02220             BOOST_UBLAS_INLINE
    02221             bool operator == (const const_iterator2 &it) const {
    02222                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    02223                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
    02224                 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
    02225                 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
    02226                 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
    02227                        (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
    02228             }
    02229             BOOST_UBLAS_INLINE
    02230             bool operator < (const const_iterator2 &it) const {
    02231                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    02232                 return it - *this > 0;
    02233             }
    02234
    02235         private:
    02236             int begin_;
    02237             int end_;
    02238             int current_;
    02239             const_subiterator1_type it1_begin_;
    02240             const_subiterator1_type it1_end_;
    02241             const_subiterator1_type it1_;
    02242             const_subiterator2_type it2_begin_;
    02243             const_subiterator2_type it2_end_;
    02244             const_subiterator2_type it2_;
    02245         };
    02246 #endif
    02247
    02248         BOOST_UBLAS_INLINE
    02249         const_iterator2 begin2 () const {
    02250             return find2 (0, 0, 0);
    02251         }
    02252         BOOST_UBLAS_INLINE
    02253         const_iterator2 end2 () const {
    02254             return find2 (0, 0, size2 ());
    02255         }
    02256
    02257 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02258         class iterator2:
    02259             public container_reference<hermitian_adaptor>,
    02260             public random_access_iterator_base<typename iterator_restrict_traits<
    02261                                                    typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
    02262                                                iterator2, value_type> {
    02263         public:
    02264             typedef typename subiterator2_type::value_type value_type;
    02265             typedef typename subiterator2_type::difference_type difference_type;
    02266             typedef typename subiterator2_type::reference reference;
    02267             typedef typename subiterator2_type::pointer pointer;
    02268
    02269             typedef iterator1 dual_iterator_type;
    02270             typedef reverse_iterator1 dual_reverse_iterator_type;
    02271
    02272             // Construction and destruction
    02273             BOOST_UBLAS_INLINE
    02274             iterator2 ():
    02275                 container_reference<self_type> (), it2_ () {}
    02276             BOOST_UBLAS_INLINE
    02277             iterator2 (self_type &m, const subiterator2_type &it2):
    02278                 container_reference<self_type> (m), it2_ (it2) {}
    02279
    02280             // Arithmetic
    02281             BOOST_UBLAS_INLINE
    02282             iterator2 &operator ++ () {
    02283                 ++ it2_;
    02284                 return *this;
    02285             }
    02286             BOOST_UBLAS_INLINE
    02287             iterator2 &operator -- () {
    02288                 -- it2_;
    02289                 return *this;
    02290             }
    02291             BOOST_UBLAS_INLINE
    02292             iterator2 &operator += (difference_type n) {
    02293                 it2_ += n;
    02294                 return *this;
    02295             }
    02296             BOOST_UBLAS_INLINE
    02297             iterator2 &operator -= (difference_type n) {
    02298                 it2_ -= n;
    02299                 return *this;
    02300             }
    02301             BOOST_UBLAS_INLINE
    02302             difference_type operator - (const iterator2 &it) const {
    02303                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    02304                 return it2_ - it.it2_;
    02305             }
    02306
    02307             // Dereference
    02308             BOOST_UBLAS_INLINE
    02309             reference operator * () const {
    02310                 return *it2_;
    02311             }
    02312             BOOST_UBLAS_INLINE
    02313             reference operator [] (difference_type n) const {
    02314                 return *(*this + n);
    02315             }
    02316
    02317 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02318             BOOST_UBLAS_INLINE
    02319 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02320             typename self_type::
    02321 #endif
    02322             iterator1 begin () const {
    02323                 return (*this) ().find1 (1, 0, index2 ());
    02324             }
    02325             BOOST_UBLAS_INLINE
    02326 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02327             typename self_type::
    02328 #endif
    02329             iterator1 end () const {
    02330                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
    02331             }
    02332             BOOST_UBLAS_INLINE
    02333 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02334             typename self_type::
    02335 #endif
    02336             reverse_iterator1 rbegin () const {
    02337                 return reverse_iterator1 (end ());
    02338             }
    02339             BOOST_UBLAS_INLINE
    02340 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02341             typename self_type::
    02342 #endif
    02343             reverse_iterator1 rend () const {
    02344                 return reverse_iterator1 (begin ());
    02345             }
    02346 #endif
    02347
    02348             // Indices
    02349             BOOST_UBLAS_INLINE
    02350             size_type index1 () const {
    02351                 return it2_.index1 ();
    02352             }
    02353             BOOST_UBLAS_INLINE
    02354             size_type index2 () const {
    02355                 return it2_.index2 ();
    02356             }
    02357
    02358             // Assignment
    02359             BOOST_UBLAS_INLINE
    02360             iterator2 &operator = (const iterator2 &it) {
    02361                 container_reference<self_type>::assign (&it ());
    02362                 it2_ = it.it2_;
    02363                 return *this;
    02364             }
    02365
    02366             // Comparison
    02367             BOOST_UBLAS_INLINE
    02368             bool operator == (const iterator2 &it) const {
    02369                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    02370                 return it2_ == it.it2_;
    02371             }
    02372             BOOST_UBLAS_INLINE
    02373             bool operator < (const iterator2 &it) const {
    02374                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    02375                 return it2_ < it.it2_;
    02376             }
    02377
    02378         private:
    02379             subiterator2_type it2_;
    02380
    02381             friend class const_iterator2;
    02382         };
    02383 #endif
    02384
    02385         BOOST_UBLAS_INLINE
    02386         iterator2 begin2 () {
    02387             return find2 (0, 0, 0);
    02388         }
    02389         BOOST_UBLAS_INLINE
    02390         iterator2 end2 () {
    02391             return find2 (0, 0, size2 ());
    02392         }
    02393
    02394         // Reverse iterators
    02395
    02396         BOOST_UBLAS_INLINE
    02397         const_reverse_iterator1 rbegin1 () const {
    02398             return const_reverse_iterator1 (end1 ());
    02399         }
    02400         BOOST_UBLAS_INLINE
    02401         const_reverse_iterator1 rend1 () const {
    02402             return const_reverse_iterator1 (begin1 ());
    02403         }
    02404
    02405         BOOST_UBLAS_INLINE
    02406         reverse_iterator1 rbegin1 () {
    02407             return reverse_iterator1 (end1 ());
    02408         }
    02409         BOOST_UBLAS_INLINE
    02410         reverse_iterator1 rend1 () {
    02411             return reverse_iterator1 (begin1 ());
    02412         }
    02413
    02414         BOOST_UBLAS_INLINE
    02415         const_reverse_iterator2 rbegin2 () const {
    02416             return const_reverse_iterator2 (end2 ());
    02417         }
    02418         BOOST_UBLAS_INLINE
    02419         const_reverse_iterator2 rend2 () const {
    02420             return const_reverse_iterator2 (begin2 ());
    02421         }
    02422
    02423         BOOST_UBLAS_INLINE
    02424         reverse_iterator2 rbegin2 () {
    02425             return reverse_iterator2 (end2 ());
    02426         }
    02427         BOOST_UBLAS_INLINE
    02428         reverse_iterator2 rend2 () {
    02429             return reverse_iterator2 (begin2 ());
    02430         }
    02431
    02432     private:
    02433         matrix_closure_type data_;
    02434         static value_type conj_;
    02435     };
    02436
    02437     template<class M, class TRI>
    02438     typename hermitian_adaptor<M, TRI>::value_type hermitian_adaptor<M, TRI>::conj_;
    02439
    02440     // Specialization for temporary_traits
    02441     template <class M, class TRI>
    02442     struct vector_temporary_traits< hermitian_adaptor<M, TRI> >
    02443     : vector_temporary_traits< M > {} ;
    02444     template <class M, class TRI>
    02445     struct vector_temporary_traits< const hermitian_adaptor<M, TRI> >
    02446     : vector_temporary_traits< M > {} ;
    02447
    02448     template <class M, class TRI>
    02449     struct matrix_temporary_traits< hermitian_adaptor<M, TRI> >
    02450     : matrix_temporary_traits< M > {} ;
    02451     template <class M, class TRI>
    02452     struct matrix_temporary_traits< const hermitian_adaptor<M, TRI> >
    02453     : matrix_temporary_traits< M > {} ;
    02454
    02455 }}}
    02456
    02457 #endif