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