Boost.uBlas 1.49
Linear Algebra in C++: matrices, vectors and numeric algorithms

hermitian.hpp

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