2 // Copyright (c) 2000-2010
3 // Joerg Walter, Mathias Koch, David Bellot
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 // The authors gratefully acknowledge the support of
10 // GeNeSys mbH & Co. KG in producing this work.
13 #ifndef BOOST_UBLAS_HERMITIAN_H
14 #define BOOST_UBLAS_HERMITIAN_H
16 #include <boost/numeric/ublas/matrix.hpp>
17 #include <boost/numeric/ublas/triangular.hpp> // for resize_preserve
18 #include <boost/numeric/ublas/detail/temporary.hpp>
20 // Iterators based on ideas of Jeremy Siek
21 // Hermitian matrices are square. Thanks to Peter Schmitteckert for spotting this.
23 namespace boost { namespace numeric { namespace ublas {
26 bool is_hermitian (const M &m) {
27 typedef typename M::size_type size_type;
29 if (m.size1 () != m.size2 ())
31 size_type size = BOOST_UBLAS_SAME (m.size1 (), m.size2 ());
32 for (size_type i = 0; i < size; ++ i) {
33 for (size_type j = i; j < size; ++ j) {
34 if (m (i, j) != conj (m (j, i)))
41 #ifdef BOOST_UBLAS_STRICT_HERMITIAN
44 class hermitian_matrix_element:
45 public container_reference<M> {
47 typedef M matrix_type;
48 typedef typename M::size_type size_type;
49 typedef typename M::value_type value_type;
50 typedef const value_type &const_reference;
51 typedef value_type &reference;
52 typedef value_type *pointer;
54 // Construction and destruction
56 hermitian_matrix_element (matrix_type &m, size_type i, size_type j, value_type d):
57 container_reference<matrix_type> (m), i_ (i), j_ (j), d_ (d), dirty_ (false) {}
59 ~hermitian_matrix_element () {
61 (*this) ().insert_element (i_, j_, d_);
66 hermitian_matrix_element &operator = (const hermitian_matrix_element &p) {
67 // Overide the implict copy assignment
74 hermitian_matrix_element &operator = (const D &d) {
81 hermitian_matrix_element &operator += (const D &d) {
88 hermitian_matrix_element &operator -= (const D &d) {
95 hermitian_matrix_element &operator *= (const D &d) {
102 hermitian_matrix_element &operator /= (const D &d) {
111 bool operator == (const D &d) const {
116 bool operator != (const D &d) const {
122 operator const_reference () const {
128 void swap (hermitian_matrix_element p) {
132 std::swap (d_, p.d_);
136 friend void swap (hermitian_matrix_element p1, hermitian_matrix_element p2) {
148 struct type_traits<hermitian_matrix_element<M> > {
149 typedef typename M::value_type element_type;
150 typedef type_traits<hermitian_matrix_element<M> > self_type;
151 typedef typename type_traits<element_type>::value_type value_type;
152 typedef typename type_traits<element_type>::const_reference const_reference;
153 typedef hermitian_matrix_element<M> reference;
154 typedef typename type_traits<element_type>::real_type real_type;
155 typedef typename type_traits<element_type>::precision_type precision_type;
157 static const unsigned plus_complexity = type_traits<element_type>::plus_complexity;
158 static const unsigned multiplies_complexity = type_traits<element_type>::multiplies_complexity;
162 real_type real (const_reference t) {
163 return type_traits<element_type>::real (t);
167 real_type imag (const_reference t) {
168 return type_traits<element_type>::imag (t);
172 value_type conj (const_reference t) {
173 return type_traits<element_type>::conj (t);
178 real_type type_abs (const_reference t) {
179 return type_traits<element_type>::type_abs (t);
183 value_type type_sqrt (const_reference t) {
184 return type_traits<element_type>::type_sqrt (t);
189 real_type norm_1 (const_reference t) {
190 return type_traits<element_type>::norm_1 (t);
194 real_type norm_2 (const_reference t) {
195 return type_traits<element_type>::norm_2 (t);
199 real_type norm_inf (const_reference t) {
200 return type_traits<element_type>::norm_inf (t);
205 bool equals (const_reference t1, const_reference t2) {
206 return type_traits<element_type>::equals (t1, t2);
210 template<class M1, class T2>
211 struct promote_traits<hermitian_matrix_element<M1>, T2> {
212 typedef typename promote_traits<typename hermitian_matrix_element<M1>::value_type, T2>::promote_type promote_type;
214 template<class T1, class M2>
215 struct promote_traits<T1, hermitian_matrix_element<M2> > {
216 typedef typename promote_traits<T1, typename hermitian_matrix_element<M2>::value_type>::promote_type promote_type;
218 template<class M1, class M2>
219 struct promote_traits<hermitian_matrix_element<M1>, hermitian_matrix_element<M2> > {
220 typedef typename promote_traits<typename hermitian_matrix_element<M1>::value_type,
221 typename hermitian_matrix_element<M2>::value_type>::promote_type promote_type;
225 /** \brief A hermitian matrix of values of type \c T
227 * For a \f$(n \times n)\f$-dimensional matrix and \f$ 0 \leq i < n, 0 \leq j < n\f$, every element
228 * \f$m_{i,j}\f$ is mapped to the \f$(i.n + j)\f$-th element of the container for row major orientation
229 * or the \f$(i + j.m)\f$-th element of the container for column major orientation. And
230 * \f$\forall i,j\f$, \f$m_{i,j} = \overline{m_{i,j}}\f$.
232 * Orientation and storage can also be specified, otherwise a row major and unbounded array are used.
233 * It is \b not required by the storage to initialize elements of the matrix.
234 * Moreover, only the given triangular matrix is stored and the storage of hermitian matrices is packed.
236 * See http://en.wikipedia.org/wiki/Hermitian_matrix for more details on hermitian matrices.
238 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
239 * \tparam TRI the type of triangular matrix is either \c lower or \c upper. Default is \c lower
240 * \tparam L the storage organization. It is either \c row_major or \c column_major. Default is \c row_major
241 * \tparam A the type of Storage array. Default is \unbounded_array.
243 template<class T, class TRI, class L, class A>
244 class hermitian_matrix:
245 public matrix_container<hermitian_matrix<T, TRI, L, A> > {
247 typedef T &true_reference;
249 typedef TRI triangular_type;
250 typedef L layout_type;
251 typedef hermitian_matrix<T, TRI, L, A> self_type;
253 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
254 using matrix_container<self_type>::operator ();
256 typedef typename A::size_type size_type;
257 typedef typename A::difference_type difference_type;
258 typedef T value_type;
259 // FIXME no better way to not return the address of a temporary?
260 // typedef const T &const_reference;
261 typedef const T const_reference;
262 #ifndef BOOST_UBLAS_STRICT_HERMITIAN
263 typedef T &reference;
265 typedef hermitian_matrix_element<self_type> reference;
267 typedef A array_type;
269 typedef const matrix_reference<const self_type> const_closure_type;
270 typedef matrix_reference<self_type> closure_type;
271 typedef vector<T, A> vector_temporary_type;
272 typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix
273 typedef packed_tag storage_category;
274 typedef typename L::orientation_category orientation_category;
276 // Construction and destruction
279 matrix_container<self_type> (),
280 size_ (0), data_ (0) {}
282 hermitian_matrix (size_type size):
283 matrix_container<self_type> (),
284 size_ (BOOST_UBLAS_SAME (size, size)), data_ (triangular_type::packed_size (layout_type (), size, size)) {
287 hermitian_matrix (size_type size1, size_type size2):
288 matrix_container<self_type> (),
289 size_ (BOOST_UBLAS_SAME (size1, size2)), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
292 hermitian_matrix (size_type size, const array_type &data):
293 matrix_container<self_type> (),
294 size_ (size), data_ (data) {}
296 hermitian_matrix (const hermitian_matrix &m):
297 matrix_container<self_type> (),
298 size_ (m.size_), data_ (m.data_) {}
301 hermitian_matrix (const matrix_expression<AE> &ae):
302 matrix_container<self_type> (),
303 size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())),
304 data_ (triangular_type::packed_size (layout_type (), size_, size_)) {
305 matrix_assign<scalar_assign> (*this, ae);
310 size_type size1 () const {
314 size_type size2 () const {
320 const array_type &data () const {
324 array_type &data () {
330 void resize (size_type size, bool preserve = true) {
332 self_type temporary (size, size);
333 detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary);
336 data ().resize (triangular_type::packed_size (layout_type (), size, size));
341 void resize (size_type size1, size_type size2, bool preserve = true) {
342 resize (BOOST_UBLAS_SAME (size1, size2), preserve);
345 void resize_packed_preserve (size_type size) {
346 size_ = BOOST_UBLAS_SAME (size, size);
347 data ().resize (triangular_type::packed_size (layout_type (), size_, size_), value_type ());
352 const_reference operator () (size_type i, size_type j) const {
353 BOOST_UBLAS_CHECK (i < size_, bad_index ());
354 BOOST_UBLAS_CHECK (j < size_, bad_index ());
356 // return type_traits<value_type>::real (data () [triangular_type::element (layout_type (), i, size_, i, size_)]);
358 if (triangular_type::other (i, j))
359 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
361 return type_traits<value_type>::conj (data () [triangular_type::element (layout_type (), j, size_, i, size_)]);
364 true_reference at_element (size_type i, size_type j) {
365 BOOST_UBLAS_CHECK (i < size_, bad_index ());
366 BOOST_UBLAS_CHECK (j < size_, bad_index ());
367 BOOST_UBLAS_CHECK (triangular_type::other (i, j), bad_index ());
368 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
371 reference operator () (size_type i, size_type j) {
372 #ifndef BOOST_UBLAS_STRICT_HERMITIAN
373 if (!triangular_type::other (i, j)) {
374 bad_index ().raise ();
377 return at_element (i, j);
379 if (triangular_type::other (i, j))
380 return reference (*this, i, j, data () [triangular_type::element (layout_type (), i, size_, j, size_)]);
382 return reference (*this, i, j, type_traits<value_type>::conj (data () [triangular_type::element (layout_type (), j, size_, i, size_)]));
386 // Element assignemnt
388 true_reference insert_element (size_type i, size_type j, const_reference t) {
389 BOOST_UBLAS_CHECK (i < size_, bad_index ());
390 BOOST_UBLAS_CHECK (j < size_, bad_index ());
391 if (triangular_type::other (i, j)) {
392 return (data () [triangular_type::element (layout_type (), i, size_, j, size_)] = t);
394 return (data () [triangular_type::element (layout_type (), j, size_, i, size_)] = type_traits<value_type>::conj (t));
398 void erase_element (size_type i, size_type j) {
399 BOOST_UBLAS_CHECK (i < size_, bad_index ());
400 BOOST_UBLAS_CHECK (j < size_, bad_index ());
401 data () [triangular_type::element (layout_type (), i, size_, j, size_)] = value_type/*zero*/();
407 std::fill (data ().begin (), data ().end (), value_type/*zero*/());
412 hermitian_matrix &operator = (const hermitian_matrix &m) {
418 hermitian_matrix &assign_temporary (hermitian_matrix &m) {
424 hermitian_matrix &operator = (const matrix_expression<AE> &ae) {
425 self_type temporary (ae);
426 return assign_temporary (temporary);
430 hermitian_matrix &assign (const matrix_expression<AE> &ae) {
431 matrix_assign<scalar_assign> (*this, ae);
436 hermitian_matrix& operator += (const matrix_expression<AE> &ae) {
437 self_type temporary (*this + ae);
438 return assign_temporary (temporary);
442 hermitian_matrix &plus_assign (const matrix_expression<AE> &ae) {
443 matrix_assign<scalar_plus_assign> (*this, ae);
448 hermitian_matrix& operator -= (const matrix_expression<AE> &ae) {
449 self_type temporary (*this - ae);
450 return assign_temporary (temporary);
454 hermitian_matrix &minus_assign (const matrix_expression<AE> &ae) {
455 matrix_assign<scalar_minus_assign> (*this, ae);
460 hermitian_matrix& operator *= (const AT &at) {
461 // Multiplication is only allowed for real scalars,
462 // otherwise the resulting matrix isn't hermitian.
463 // Thanks to Peter Schmitteckert for spotting this.
464 BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
465 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
470 hermitian_matrix& operator /= (const AT &at) {
471 // Multiplication is only allowed for real scalars,
472 // otherwise the resulting matrix isn't hermitian.
473 // Thanks to Peter Schmitteckert for spotting this.
474 BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
475 matrix_assign_scalar<scalar_divides_assign> (*this, at);
481 void swap (hermitian_matrix &m) {
483 std::swap (size_, m.size_);
484 data ().swap (m.data ());
488 friend void swap (hermitian_matrix &m1, hermitian_matrix &m2) {
493 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
494 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
495 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
496 typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
497 typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
499 class const_iterator1;
501 class const_iterator2;
504 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
505 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
506 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
507 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
511 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
512 return const_iterator1 (*this, i, j);
515 iterator1 find1 (int rank, size_type i, size_type j) {
517 i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
519 i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
520 return iterator1 (*this, i, j);
523 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
524 return const_iterator2 (*this, i, j);
527 iterator2 find2 (int rank, size_type i, size_type j) {
529 j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
531 j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
532 return iterator2 (*this, i, j);
535 // Iterators simply are indices.
537 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
538 class const_iterator1:
539 public container_const_reference<hermitian_matrix>,
540 public random_access_iterator_base<packed_random_access_iterator_tag,
541 const_iterator1, value_type> {
543 typedef typename hermitian_matrix::value_type value_type;
544 typedef typename hermitian_matrix::difference_type difference_type;
545 typedef typename hermitian_matrix::const_reference reference;
546 typedef const typename hermitian_matrix::pointer pointer;
548 typedef const_iterator2 dual_iterator_type;
549 typedef const_reverse_iterator2 dual_reverse_iterator_type;
551 // Construction and destruction
554 container_const_reference<self_type> (), it1_ (), it2_ () {}
556 const_iterator1 (const self_type &m, size_type it1, size_type it2):
557 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
559 const_iterator1 (const iterator1 &it):
560 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
564 const_iterator1 &operator ++ () {
569 const_iterator1 &operator -- () {
574 const_iterator1 &operator += (difference_type n) {
579 const_iterator1 &operator -= (difference_type n) {
584 difference_type operator - (const const_iterator1 &it) const {
585 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
586 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
587 return it1_ - it.it1_;
592 const_reference operator * () const {
593 return (*this) () (it1_, it2_);
596 const_reference operator [] (difference_type n) const {
600 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
602 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
605 const_iterator2 begin () const {
606 return (*this) ().find2 (1, it1_, 0);
609 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
612 const_iterator2 cbegin () const {
616 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
619 const_iterator2 end () const {
620 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
623 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
626 const_iterator2 cend () const {
630 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
633 const_reverse_iterator2 rbegin () const {
634 return const_reverse_iterator2 (end ());
637 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
640 const_reverse_iterator2 crbegin () const {
644 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
647 const_reverse_iterator2 rend () const {
648 return const_reverse_iterator2 (begin ());
651 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
654 const_reverse_iterator2 crend () const {
661 size_type index1 () const {
665 size_type index2 () const {
671 const_iterator1 &operator = (const const_iterator1 &it) {
672 container_const_reference<self_type>::assign (&it ());
680 bool operator == (const const_iterator1 &it) const {
681 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
682 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
683 return it1_ == it.it1_;
686 bool operator < (const const_iterator1 &it) const {
687 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
688 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
689 return it1_ < it.it1_;
699 const_iterator1 begin1 () const {
700 return find1 (0, 0, 0);
703 const_iterator1 cbegin1 () const {
707 const_iterator1 end1 () const {
708 return find1 (0, size_, 0);
711 const_iterator1 cend1 () const {
715 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
717 public container_reference<hermitian_matrix>,
718 public random_access_iterator_base<packed_random_access_iterator_tag,
719 iterator1, value_type> {
721 typedef typename hermitian_matrix::value_type value_type;
722 typedef typename hermitian_matrix::difference_type difference_type;
723 typedef typename hermitian_matrix::true_reference reference;
724 typedef typename hermitian_matrix::pointer pointer;
726 typedef iterator2 dual_iterator_type;
727 typedef reverse_iterator2 dual_reverse_iterator_type;
729 // Construction and destruction
732 container_reference<self_type> (), it1_ (), it2_ () {}
734 iterator1 (self_type &m, size_type it1, size_type it2):
735 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
739 iterator1 &operator ++ () {
744 iterator1 &operator -- () {
749 iterator1 &operator += (difference_type n) {
754 iterator1 &operator -= (difference_type n) {
759 difference_type operator - (const iterator1 &it) const {
760 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
761 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
762 return it1_ - it.it1_;
767 reference operator * () const {
768 return (*this) ().at_element (it1_, it2_);
771 reference operator [] (difference_type n) const {
775 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
777 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
780 iterator2 begin () const {
781 return (*this) ().find2 (1, it1_, 0);
784 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
787 iterator2 end () const {
788 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
791 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
794 reverse_iterator2 rbegin () const {
795 return reverse_iterator2 (end ());
798 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
801 reverse_iterator2 rend () const {
802 return reverse_iterator2 (begin ());
808 size_type index1 () const {
812 size_type index2 () const {
818 iterator1 &operator = (const iterator1 &it) {
819 container_reference<self_type>::assign (&it ());
827 bool operator == (const iterator1 &it) const {
828 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
829 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
830 return it1_ == it.it1_;
833 bool operator < (const iterator1 &it) const {
834 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
835 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
836 return it1_ < it.it1_;
843 friend class const_iterator1;
848 iterator1 begin1 () {
849 return find1 (0, 0, 0);
853 return find1 (0, size_, 0);
856 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
857 class const_iterator2:
858 public container_const_reference<hermitian_matrix>,
859 public random_access_iterator_base<packed_random_access_iterator_tag,
860 const_iterator2, value_type> {
862 typedef typename hermitian_matrix::value_type value_type;
863 typedef typename hermitian_matrix::difference_type difference_type;
864 typedef typename hermitian_matrix::const_reference reference;
865 typedef const typename hermitian_matrix::pointer pointer;
867 typedef const_iterator1 dual_iterator_type;
868 typedef const_reverse_iterator1 dual_reverse_iterator_type;
870 // Construction and destruction
873 container_const_reference<self_type> (), it1_ (), it2_ () {}
875 const_iterator2 (const self_type &m, size_type it1, size_type it2):
876 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
878 const_iterator2 (const iterator2 &it):
879 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
883 const_iterator2 &operator ++ () {
888 const_iterator2 &operator -- () {
893 const_iterator2 &operator += (difference_type n) {
898 const_iterator2 &operator -= (difference_type n) {
903 difference_type operator - (const const_iterator2 &it) const {
904 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
905 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
906 return it2_ - it.it2_;
911 const_reference operator * () const {
912 return (*this) () (it1_, it2_);
915 const_reference operator [] (difference_type n) const {
919 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
921 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
924 const_iterator1 begin () const {
925 return (*this) ().find1 (1, 0, it2_);
928 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
931 const_iterator1 cbegin () const {
935 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
938 const_iterator1 end () const {
939 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
942 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
945 const_iterator1 cend () const {
949 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
952 const_reverse_iterator1 rbegin () const {
953 return const_reverse_iterator1 (end ());
956 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
959 const_iterator1 crbegin () const {
963 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
966 const_reverse_iterator1 rend () const {
967 return const_reverse_iterator1 (begin ());
970 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
973 const_iterator1 crend () const {
980 size_type index1 () const {
984 size_type index2 () const {
990 const_iterator2 &operator = (const const_iterator2 &it) {
991 container_const_reference<self_type>::assign (&it ());
999 bool operator == (const const_iterator2 &it) const {
1000 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1001 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1002 return it2_ == it.it2_;
1005 bool operator < (const const_iterator2 &it) const {
1006 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1007 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1008 return it2_ < it.it2_;
1018 const_iterator2 begin2 () const {
1019 return find2 (0, 0, 0);
1022 const_iterator2 cbegin2 () const {
1026 const_iterator2 end2 () const {
1027 return find2 (0, 0, size_);
1030 const_iterator2 cend2 () const {
1034 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1036 public container_reference<hermitian_matrix>,
1037 public random_access_iterator_base<packed_random_access_iterator_tag,
1038 iterator2, value_type> {
1040 typedef typename hermitian_matrix::value_type value_type;
1041 typedef typename hermitian_matrix::difference_type difference_type;
1042 typedef typename hermitian_matrix::true_reference reference;
1043 typedef typename hermitian_matrix::pointer pointer;
1045 typedef iterator1 dual_iterator_type;
1046 typedef reverse_iterator1 dual_reverse_iterator_type;
1048 // Construction and destruction
1051 container_reference<self_type> (), it1_ (), it2_ () {}
1053 iterator2 (self_type &m, size_type it1, size_type it2):
1054 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
1058 iterator2 &operator ++ () {
1063 iterator2 &operator -- () {
1068 iterator2 &operator += (difference_type n) {
1073 iterator2 &operator -= (difference_type n) {
1078 difference_type operator - (const iterator2 &it) const {
1079 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1080 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1081 return it2_ - it.it2_;
1086 reference operator * () const {
1087 return (*this) ().at_element (it1_, it2_);
1090 reference operator [] (difference_type n) const {
1091 return *(*this + n);
1094 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1096 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1097 typename self_type::
1099 iterator1 begin () const {
1100 return (*this) ().find1 (1, 0, it2_);
1103 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1104 typename self_type::
1106 iterator1 end () const {
1107 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
1110 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1111 typename self_type::
1113 reverse_iterator1 rbegin () const {
1114 return reverse_iterator1 (end ());
1117 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1118 typename self_type::
1120 reverse_iterator1 rend () const {
1121 return reverse_iterator1 (begin ());
1127 size_type index1 () const {
1131 size_type index2 () const {
1137 iterator2 &operator = (const iterator2 &it) {
1138 container_reference<self_type>::assign (&it ());
1146 bool operator == (const iterator2 &it) const {
1147 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1148 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1149 return it2_ == it.it2_;
1152 bool operator < (const iterator2 &it) const {
1153 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1154 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1155 return it2_ < it.it2_;
1162 friend class const_iterator2;
1167 iterator2 begin2 () {
1168 return find2 (0, 0, 0);
1172 return find2 (0, 0, size_);
1175 // Reverse iterators
1178 const_reverse_iterator1 rbegin1 () const {
1179 return const_reverse_iterator1 (end1 ());
1182 const_reverse_iterator1 crbegin1 () const {
1186 const_reverse_iterator1 rend1 () const {
1187 return const_reverse_iterator1 (begin1 ());
1190 const_reverse_iterator1 crend1 () const {
1195 reverse_iterator1 rbegin1 () {
1196 return reverse_iterator1 (end1 ());
1199 reverse_iterator1 rend1 () {
1200 return reverse_iterator1 (begin1 ());
1204 const_reverse_iterator2 rbegin2 () const {
1205 return const_reverse_iterator2 (end2 ());
1208 const_reverse_iterator2 crbegin2 () const {
1212 const_reverse_iterator2 rend2 () const {
1213 return const_reverse_iterator2 (begin2 ());
1216 const_reverse_iterator2 crend2 () const {
1221 reverse_iterator2 rbegin2 () {
1222 return reverse_iterator2 (end2 ());
1225 reverse_iterator2 rend2 () {
1226 return reverse_iterator2 (begin2 ());
1234 /** \brief A Hermitian matrix adaptator: convert a any matrix into a Hermitian matrix expression
1236 * For a \f$(m\times n)\f$-dimensional matrix, the \c hermitian_adaptor will provide a hermitian matrix.
1237 * Storage and location are based on those of the underlying matrix. This is important because
1238 * a \c hermitian_adaptor does not copy the matrix data to a new place. Therefore, modifying values
1239 * in a \c hermitian_adaptor matrix will also modify the underlying matrix too.
1241 * \tparam M the type of matrix used to generate a hermitian matrix
1243 template<class M, class TRI>
1244 class hermitian_adaptor:
1245 public matrix_expression<hermitian_adaptor<M, TRI> > {
1247 typedef hermitian_adaptor<M, TRI> self_type;
1248 typedef typename M::value_type &true_reference;
1250 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1251 using matrix_expression<self_type>::operator ();
1253 typedef const M const_matrix_type;
1254 typedef M matrix_type;
1255 typedef TRI triangular_type;
1256 typedef typename M::size_type size_type;
1257 typedef typename M::difference_type difference_type;
1258 typedef typename M::value_type value_type;
1259 typedef typename M::value_type const_reference;
1260 #ifndef BOOST_UBLAS_STRICT_HERMITIAN
1261 typedef typename boost::mpl::if_<boost::is_const<M>,
1262 typename M::value_type,
1263 typename M::reference>::type reference;
1265 typedef typename boost::mpl::if_<boost::is_const<M>,
1266 typename M::value_type,
1267 hermitian_matrix_element<self_type> >::type reference;
1269 typedef typename boost::mpl::if_<boost::is_const<M>,
1270 typename M::const_closure_type,
1271 typename M::closure_type>::type matrix_closure_type;
1272 typedef const self_type const_closure_type;
1273 typedef self_type closure_type;
1274 // Replaced by _temporary_traits to avoid type requirements on M
1275 //typedef typename M::vector_temporary_type vector_temporary_type;
1276 //typedef typename M::matrix_temporary_type matrix_temporary_type;
1277 typedef typename storage_restrict_traits<typename M::storage_category,
1278 packed_proxy_tag>::storage_category storage_category;
1279 typedef typename M::orientation_category orientation_category;
1281 // Construction and destruction
1283 hermitian_adaptor (matrix_type &data):
1284 matrix_expression<self_type> (),
1286 BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
1289 hermitian_adaptor (const hermitian_adaptor &m):
1290 matrix_expression<self_type> (),
1292 BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
1297 size_type size1 () const {
1298 return data_.size1 ();
1301 size_type size2 () const {
1302 return data_.size2 ();
1305 // Storage accessors
1307 const matrix_closure_type &data () const {
1311 matrix_closure_type &data () {
1316 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1318 const_reference operator () (size_type i, size_type j) const {
1319 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1320 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1322 // return type_traits<value_type>::real (data () (i, i));
1324 if (triangular_type::other (i, j))
1325 return data () (i, j);
1327 return type_traits<value_type>::conj (data () (j, i));
1330 reference operator () (size_type i, size_type j) {
1331 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1332 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1333 #ifndef BOOST_UBLAS_STRICT_HERMITIAN
1334 if (triangular_type::other (i, j))
1335 return data () (i, j);
1337 external_logic ().raise ();
1338 return conj_ = type_traits<value_type>::conj (data () (j, i));
1341 if (triangular_type::other (i, j))
1342 return reference (*this, i, j, data () (i, j));
1344 return reference (*this, i, j, type_traits<value_type>::conj (data () (j, i)));
1348 true_reference insert_element (size_type i, size_type j, value_type t) {
1349 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1350 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1352 // data () (i, i) = type_traits<value_type>::real (t);
1354 if (triangular_type::other (i, j))
1355 return data () (i, j) = t;
1357 return data () (j, i) = type_traits<value_type>::conj (t);
1361 reference operator () (size_type i, size_type j) {
1362 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1363 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1364 #ifndef BOOST_UBLAS_STRICT_HERMITIAN
1365 if (triangular_type::other (i, j))
1366 return data () (i, j);
1368 external_logic ().raise ();
1369 return conj_ = type_traits<value_type>::conj (data () (j, i));
1372 if (triangular_type::other (i, j))
1373 return reference (*this, i, j, data () (i, j));
1375 return reference (*this, i, j, type_traits<value_type>::conj (data () (j, i)));
1379 true_reference insert_element (size_type i, size_type j, value_type t) {
1380 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1381 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1383 // data () (i, i) = type_traits<value_type>::real (t);
1385 if (triangular_type::other (i, j))
1386 return data () (i, j) = t;
1388 return data () (j, i) = type_traits<value_type>::conj (t);
1394 hermitian_adaptor &operator = (const hermitian_adaptor &m) {
1395 matrix_assign<scalar_assign, triangular_type> (*this, m);
1399 hermitian_adaptor &assign_temporary (hermitian_adaptor &m) {
1405 hermitian_adaptor &operator = (const matrix_expression<AE> &ae) {
1406 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae));
1411 hermitian_adaptor &assign (const matrix_expression<AE> &ae) {
1412 matrix_assign<scalar_assign, triangular_type> (*this, ae);
1417 hermitian_adaptor& operator += (const matrix_expression<AE> &ae) {
1418 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae));
1423 hermitian_adaptor &plus_assign (const matrix_expression<AE> &ae) {
1424 matrix_assign<scalar_plus_assign, triangular_type> (*this, ae);
1429 hermitian_adaptor& operator -= (const matrix_expression<AE> &ae) {
1430 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae));
1435 hermitian_adaptor &minus_assign (const matrix_expression<AE> &ae) {
1436 matrix_assign<scalar_minus_assign, triangular_type> (*this, ae);
1441 hermitian_adaptor& operator *= (const AT &at) {
1442 // Multiplication is only allowed for real scalars,
1443 // otherwise the resulting matrix isn't hermitian.
1444 // Thanks to Peter Schmitteckert for spotting this.
1445 BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
1446 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
1451 hermitian_adaptor& operator /= (const AT &at) {
1452 // Multiplication is only allowed for real scalars,
1453 // otherwise the resulting matrix isn't hermitian.
1454 // Thanks to Peter Schmitteckert for spotting this.
1455 BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
1456 matrix_assign_scalar<scalar_divides_assign> (*this, at);
1460 // Closure comparison
1462 bool same_closure (const hermitian_adaptor &ha) const {
1463 return (*this).data ().same_closure (ha.data ());
1468 void swap (hermitian_adaptor &m) {
1470 matrix_swap<scalar_swap, triangular_type> (*this, m);
1473 friend void swap (hermitian_adaptor &m1, hermitian_adaptor &m2) {
1479 // Use matrix iterator
1480 typedef typename M::const_iterator1 const_subiterator1_type;
1481 typedef typename boost::mpl::if_<boost::is_const<M>,
1482 typename M::const_iterator1,
1483 typename M::iterator1>::type subiterator1_type;
1484 typedef typename M::const_iterator2 const_subiterator2_type;
1485 typedef typename boost::mpl::if_<boost::is_const<M>,
1486 typename M::const_iterator2,
1487 typename M::iterator2>::type subiterator2_type;
1490 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1491 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
1492 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
1493 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
1494 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
1496 class const_iterator1;
1498 class const_iterator2;
1501 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1502 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
1503 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1504 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
1508 const_iterator1 find1 (int rank, size_type i, size_type j) const {
1509 if (triangular_type::other (i, j)) {
1510 if (triangular_type::other (size1 (), j)) {
1511 return const_iterator1 (*this, 0, 0,
1512 data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j),
1513 data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ()));
1515 return const_iterator1 (*this, 0, 1,
1516 data ().find1 (rank, i, j), data ().find1 (rank, j, j),
1517 data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ()));
1520 if (triangular_type::other (size1 (), j)) {
1521 return const_iterator1 (*this, 1, 0,
1522 data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j),
1523 data ().find2 (rank, j, i), data ().find2 (rank, j, j));
1525 return const_iterator1 (*this, 1, 1,
1526 data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()),
1527 data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ()));
1532 iterator1 find1 (int rank, size_type i, size_type j) {
1534 i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
1536 i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
1537 return iterator1 (*this, data ().find1 (rank, i, j));
1540 const_iterator2 find2 (int rank, size_type i, size_type j) const {
1541 if (triangular_type::other (i, j)) {
1542 if (triangular_type::other (i, size2 ())) {
1543 return const_iterator2 (*this, 1, 1,
1544 data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()),
1545 data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ()));
1547 return const_iterator2 (*this, 1, 0,
1548 data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i),
1549 data ().find2 (rank, i, j), data ().find2 (rank, i, i));
1552 if (triangular_type::other (i, size2 ())) {
1553 return const_iterator2 (*this, 0, 1,
1554 data ().find1 (rank, j, i), data ().find1 (rank, i, i),
1555 data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ()));
1557 return const_iterator2 (*this, 0, 0,
1558 data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i),
1559 data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ()));
1564 iterator2 find2 (int rank, size_type i, size_type j) {
1566 j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
1568 j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
1569 return iterator2 (*this, data ().find2 (rank, i, j));
1572 // Iterators simply are indices.
1574 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1575 class const_iterator1:
1576 public container_const_reference<hermitian_adaptor>,
1577 public random_access_iterator_base<typename iterator_restrict_traits<
1578 typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
1579 const_iterator1, value_type> {
1581 typedef typename const_subiterator1_type::value_type value_type;
1582 typedef typename const_subiterator1_type::difference_type difference_type;
1583 // FIXME no better way to not return the address of a temporary?
1584 // typedef typename const_subiterator1_type::reference reference;
1585 typedef typename const_subiterator1_type::value_type reference;
1586 typedef typename const_subiterator1_type::pointer pointer;
1588 typedef const_iterator2 dual_iterator_type;
1589 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1591 // Construction and destruction
1594 container_const_reference<self_type> (),
1595 begin_ (-1), end_ (-1), current_ (-1),
1596 it1_begin_ (), it1_end_ (), it1_ (),
1597 it2_begin_ (), it2_end_ (), it2_ () {}
1599 const_iterator1 (const self_type &m, int begin, int end,
1600 const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
1601 const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
1602 container_const_reference<self_type> (m),
1603 begin_ (begin), end_ (end), current_ (begin),
1604 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
1605 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
1606 if (current_ == 0 && it1_ == it1_end_)
1608 if (current_ == 1 && it2_ == it2_end_)
1610 if ((current_ == 0 && it1_ == it1_end_) ||
1611 (current_ == 1 && it2_ == it2_end_))
1613 BOOST_UBLAS_CHECK (current_ == end_ ||
1614 (current_ == 0 && it1_ != it1_end_) ||
1615 (current_ == 1 && it2_ != it2_end_), internal_logic ());
1617 // FIXME cannot compile
1618 // iterator1 does not have these members!
1620 const_iterator1 (const iterator1 &it):
1621 container_const_reference<self_type> (it ()),
1622 begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
1623 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
1624 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
1625 BOOST_UBLAS_CHECK (current_ == end_ ||
1626 (current_ == 0 && it1_ != it1_end_) ||
1627 (current_ == 1 && it2_ != it2_end_), internal_logic ());
1632 const_iterator1 &operator ++ () {
1633 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1634 if (current_ == 0) {
1635 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1637 if (it1_ == it1_end_ && end_ == 1) {
1641 } else /* if (current_ == 1) */ {
1642 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1644 if (it2_ == it2_end_ && end_ == 0) {
1652 const_iterator1 &operator -- () {
1653 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1654 if (current_ == 0) {
1655 if (it1_ == it1_begin_ && begin_ == 1) {
1657 BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
1663 } else /* if (current_ == 1) */ {
1664 if (it2_ == it2_begin_ && begin_ == 0) {
1666 BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
1676 const_iterator1 &operator += (difference_type n) {
1677 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1678 if (current_ == 0) {
1679 size_type d = (std::min) (n, it1_end_ - it1_);
1682 if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
1683 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1684 d = (std::min) (n, it2_end_ - it2_begin_);
1685 it2_ = it2_begin_ + d;
1689 } else /* if (current_ == 1) */ {
1690 size_type d = (std::min) (n, it2_end_ - it2_);
1693 if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
1694 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1695 d = (std::min) (n, it1_end_ - it1_begin_);
1696 it1_ = it1_begin_ + d;
1701 BOOST_UBLAS_CHECK (n == 0, external_logic ());
1705 const_iterator1 &operator -= (difference_type n) {
1706 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1707 if (current_ == 0) {
1708 size_type d = (std::min) (n, it1_ - it1_begin_);
1712 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1713 d = (std::min) (n, it2_end_ - it2_begin_);
1714 it2_ = it2_end_ - d;
1718 } else /* if (current_ == 1) */ {
1719 size_type d = (std::min) (n, it2_ - it2_begin_);
1723 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1724 d = (std::min) (n, it1_end_ - it1_begin_);
1725 it1_ = it1_end_ - d;
1730 BOOST_UBLAS_CHECK (n == 0, external_logic ());
1734 difference_type operator - (const const_iterator1 &it) const {
1735 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1736 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1737 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1738 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1739 if (current_ == 0 && it.current_ == 0) {
1740 return it1_ - it.it1_;
1741 } else if (current_ == 0 && it.current_ == 1) {
1742 if (end_ == 1 && it.end_ == 1) {
1743 return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
1744 } else /* if (end_ == 0 && it.end_ == 0) */ {
1745 return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
1748 } else if (current_ == 1 && it.current_ == 0) {
1749 if (end_ == 1 && it.end_ == 1) {
1750 return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
1751 } else /* if (end_ == 0 && it.end_ == 0) */ {
1752 return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
1754 } else /* if (current_ == 1 && it.current_ == 1) */ {
1755 return it2_ - it.it2_;
1761 const_reference operator * () const {
1762 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1763 if (current_ == 0) {
1764 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1765 if (triangular_type::other (index1 (), index2 ()))
1768 return type_traits<value_type>::conj (*it1_);
1769 } else /* if (current_ == 1) */ {
1770 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1771 if (triangular_type::other (index1 (), index2 ()))
1774 return type_traits<value_type>::conj (*it2_);
1778 const_reference operator [] (difference_type n) const {
1779 return *(*this + n);
1782 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1784 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1785 typename self_type::
1787 const_iterator2 begin () const {
1788 return (*this) ().find2 (1, index1 (), 0);
1791 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1792 typename self_type::
1794 const_iterator2 cbegin () const {
1798 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1799 typename self_type::
1801 const_iterator2 end () const {
1802 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1805 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1806 typename self_type::
1808 const_iterator2 cend () const {
1812 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1813 typename self_type::
1815 const_reverse_iterator2 rbegin () const {
1816 return const_reverse_iterator2 (end ());
1819 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1820 typename self_type::
1822 const_reverse_iterator2 crbegin () const {
1826 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1827 typename self_type::
1829 const_reverse_iterator2 rend () const {
1830 return const_reverse_iterator2 (begin ());
1833 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1834 typename self_type::
1836 const_reverse_iterator2 crend () const {
1843 size_type index1 () const {
1844 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1845 if (current_ == 0) {
1846 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1847 return it1_.index1 ();
1848 } else /* if (current_ == 1) */ {
1849 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1850 return it2_.index2 ();
1854 size_type index2 () const {
1855 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1856 if (current_ == 0) {
1857 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1858 return it1_.index2 ();
1859 } else /* if (current_ == 1) */ {
1860 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1861 return it2_.index1 ();
1867 const_iterator1 &operator = (const const_iterator1 &it) {
1868 container_const_reference<self_type>::assign (&it ());
1871 current_ = it.current_;
1872 it1_begin_ = it.it1_begin_;
1873 it1_end_ = it.it1_end_;
1875 it2_begin_ = it.it2_begin_;
1876 it2_end_ = it.it2_end_;
1883 bool operator == (const const_iterator1 &it) const {
1884 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1885 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1886 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1887 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1888 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
1889 (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
1892 bool operator < (const const_iterator1 &it) const {
1893 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1894 return it - *this > 0;
1901 const_subiterator1_type it1_begin_;
1902 const_subiterator1_type it1_end_;
1903 const_subiterator1_type it1_;
1904 const_subiterator2_type it2_begin_;
1905 const_subiterator2_type it2_end_;
1906 const_subiterator2_type it2_;
1911 const_iterator1 begin1 () const {
1912 return find1 (0, 0, 0);
1915 const_iterator1 cbegin1 () const {
1919 const_iterator1 end1 () const {
1920 return find1 (0, size1 (), 0);
1923 const_iterator1 cend1 () const {
1927 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1929 public container_reference<hermitian_adaptor>,
1930 public random_access_iterator_base<typename iterator_restrict_traits<
1931 typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1932 iterator1, value_type> {
1934 typedef typename subiterator1_type::value_type value_type;
1935 typedef typename subiterator1_type::difference_type difference_type;
1936 typedef typename subiterator1_type::reference reference;
1937 typedef typename subiterator1_type::pointer pointer;
1939 typedef iterator2 dual_iterator_type;
1940 typedef reverse_iterator2 dual_reverse_iterator_type;
1942 // Construction and destruction
1945 container_reference<self_type> (), it1_ () {}
1947 iterator1 (self_type &m, const subiterator1_type &it1):
1948 container_reference<self_type> (m), it1_ (it1) {}
1952 iterator1 &operator ++ () {
1957 iterator1 &operator -- () {
1962 iterator1 &operator += (difference_type n) {
1967 iterator1 &operator -= (difference_type n) {
1972 difference_type operator - (const iterator1 &it) const {
1973 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1974 return it1_ - it.it1_;
1979 reference operator * () const {
1983 reference operator [] (difference_type n) const {
1984 return *(*this + n);
1987 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1989 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1990 typename self_type::
1992 iterator2 begin () const {
1993 return (*this) ().find2 (1, index1 (), 0);
1996 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1997 typename self_type::
1999 iterator2 end () const {
2000 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
2003 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2004 typename self_type::
2006 reverse_iterator2 rbegin () const {
2007 return reverse_iterator2 (end ());
2010 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2011 typename self_type::
2013 reverse_iterator2 rend () const {
2014 return reverse_iterator2 (begin ());
2020 size_type index1 () const {
2021 return it1_.index1 ();
2024 size_type index2 () const {
2025 return it1_.index2 ();
2030 iterator1 &operator = (const iterator1 &it) {
2031 container_reference<self_type>::assign (&it ());
2038 bool operator == (const iterator1 &it) const {
2039 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2040 return it1_ == it.it1_;
2043 bool operator < (const iterator1 &it) const {
2044 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2045 return it1_ < it.it1_;
2049 subiterator1_type it1_;
2051 friend class const_iterator1;
2056 iterator1 begin1 () {
2057 return find1 (0, 0, 0);
2061 return find1 (0, size1 (), 0);
2064 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2065 class const_iterator2:
2066 public container_const_reference<hermitian_adaptor>,
2067 public random_access_iterator_base<typename iterator_restrict_traits<
2068 typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
2069 const_iterator2, value_type> {
2071 typedef typename const_subiterator2_type::value_type value_type;
2072 typedef typename const_subiterator2_type::difference_type difference_type;
2073 // FIXME no better way to not return the address of a temporary?
2074 // typedef typename const_subiterator2_type::reference reference;
2075 typedef typename const_subiterator2_type::value_type reference;
2076 typedef typename const_subiterator2_type::pointer pointer;
2078 typedef const_iterator1 dual_iterator_type;
2079 typedef const_reverse_iterator1 dual_reverse_iterator_type;
2081 // Construction and destruction
2084 container_const_reference<self_type> (),
2085 begin_ (-1), end_ (-1), current_ (-1),
2086 it1_begin_ (), it1_end_ (), it1_ (),
2087 it2_begin_ (), it2_end_ (), it2_ () {}
2089 const_iterator2 (const self_type &m, int begin, int end,
2090 const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
2091 const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
2092 container_const_reference<self_type> (m),
2093 begin_ (begin), end_ (end), current_ (begin),
2094 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
2095 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
2096 if (current_ == 0 && it1_ == it1_end_)
2098 if (current_ == 1 && it2_ == it2_end_)
2100 if ((current_ == 0 && it1_ == it1_end_) ||
2101 (current_ == 1 && it2_ == it2_end_))
2103 BOOST_UBLAS_CHECK (current_ == end_ ||
2104 (current_ == 0 && it1_ != it1_end_) ||
2105 (current_ == 1 && it2_ != it2_end_), internal_logic ());
2107 // FIXME cannot compiler
2108 // iterator2 does not have these members!
2110 const_iterator2 (const iterator2 &it):
2111 container_const_reference<self_type> (it ()),
2112 begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
2113 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
2114 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
2115 BOOST_UBLAS_CHECK (current_ == end_ ||
2116 (current_ == 0 && it1_ != it1_end_) ||
2117 (current_ == 1 && it2_ != it2_end_), internal_logic ());
2122 const_iterator2 &operator ++ () {
2123 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
2124 if (current_ == 0) {
2125 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
2127 if (it1_ == it1_end_ && end_ == 1) {
2131 } else /* if (current_ == 1) */ {
2132 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
2134 if (it2_ == it2_end_ && end_ == 0) {
2142 const_iterator2 &operator -- () {
2143 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
2144 if (current_ == 0) {
2145 if (it1_ == it1_begin_ && begin_ == 1) {
2147 BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
2153 } else /* if (current_ == 1) */ {
2154 if (it2_ == it2_begin_ && begin_ == 0) {
2156 BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
2166 const_iterator2 &operator += (difference_type n) {
2167 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
2168 if (current_ == 0) {
2169 size_type d = (std::min) (n, it1_end_ - it1_);
2172 if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
2173 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
2174 d = (std::min) (n, it2_end_ - it2_begin_);
2175 it2_ = it2_begin_ + d;
2179 } else /* if (current_ == 1) */ {
2180 size_type d = (std::min) (n, it2_end_ - it2_);
2183 if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
2184 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
2185 d = (std::min) (n, it1_end_ - it1_begin_);
2186 it1_ = it1_begin_ + d;
2191 BOOST_UBLAS_CHECK (n == 0, external_logic ());
2195 const_iterator2 &operator -= (difference_type n) {
2196 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
2197 if (current_ == 0) {
2198 size_type d = (std::min) (n, it1_ - it1_begin_);
2202 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
2203 d = (std::min) (n, it2_end_ - it2_begin_);
2204 it2_ = it2_end_ - d;
2208 } else /* if (current_ == 1) */ {
2209 size_type d = (std::min) (n, it2_ - it2_begin_);
2213 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
2214 d = (std::min) (n, it1_end_ - it1_begin_);
2215 it1_ = it1_end_ - d;
2220 BOOST_UBLAS_CHECK (n == 0, external_logic ());
2224 difference_type operator - (const const_iterator2 &it) const {
2225 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2226 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
2227 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
2228 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
2229 if (current_ == 0 && it.current_ == 0) {
2230 return it1_ - it.it1_;
2231 } else if (current_ == 0 && it.current_ == 1) {
2232 if (end_ == 1 && it.end_ == 1) {
2233 return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
2234 } else /* if (end_ == 0 && it.end_ == 0) */ {
2235 return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
2238 } else if (current_ == 1 && it.current_ == 0) {
2239 if (end_ == 1 && it.end_ == 1) {
2240 return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
2241 } else /* if (end_ == 0 && it.end_ == 0) */ {
2242 return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
2244 } else /* if (current_ == 1 && it.current_ == 1) */ {
2245 return it2_ - it.it2_;
2251 const_reference operator * () const {
2252 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
2253 if (current_ == 0) {
2254 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
2255 if (triangular_type::other (index1 (), index2 ()))
2258 return type_traits<value_type>::conj (*it1_);
2259 } else /* if (current_ == 1) */ {
2260 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
2261 if (triangular_type::other (index1 (), index2 ()))
2264 return type_traits<value_type>::conj (*it2_);
2268 const_reference operator [] (difference_type n) const {
2269 return *(*this + n);
2272 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2274 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2275 typename self_type::
2277 const_iterator1 begin () const {
2278 return (*this) ().find1 (1, 0, index2 ());
2281 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2282 typename self_type::
2284 const_iterator1 cbegin () const {
2288 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2289 typename self_type::
2291 const_iterator1 end () const {
2292 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
2295 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2296 typename self_type::
2298 const_iterator1 cend () const {
2302 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2303 typename self_type::
2305 const_reverse_iterator1 rbegin () const {
2306 return const_reverse_iterator1 (end ());
2309 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2310 typename self_type::
2312 const_reverse_iterator1 crbegin () const {
2316 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2317 typename self_type::
2319 const_reverse_iterator1 rend () const {
2320 return const_reverse_iterator1 (begin ());
2323 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2324 typename self_type::
2326 const_reverse_iterator1 crend () const {
2333 size_type index1 () const {
2334 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
2335 if (current_ == 0) {
2336 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
2337 return it1_.index2 ();
2338 } else /* if (current_ == 1) */ {
2339 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
2340 return it2_.index1 ();
2344 size_type index2 () const {
2345 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
2346 if (current_ == 0) {
2347 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
2348 return it1_.index1 ();
2349 } else /* if (current_ == 1) */ {
2350 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
2351 return it2_.index2 ();
2357 const_iterator2 &operator = (const const_iterator2 &it) {
2358 container_const_reference<self_type>::assign (&it ());
2361 current_ = it.current_;
2362 it1_begin_ = it.it1_begin_;
2363 it1_end_ = it.it1_end_;
2365 it2_begin_ = it.it2_begin_;
2366 it2_end_ = it.it2_end_;
2373 bool operator == (const const_iterator2 &it) const {
2374 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2375 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
2376 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
2377 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
2378 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
2379 (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
2382 bool operator < (const const_iterator2 &it) const {
2383 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2384 return it - *this > 0;
2391 const_subiterator1_type it1_begin_;
2392 const_subiterator1_type it1_end_;
2393 const_subiterator1_type it1_;
2394 const_subiterator2_type it2_begin_;
2395 const_subiterator2_type it2_end_;
2396 const_subiterator2_type it2_;
2401 const_iterator2 begin2 () const {
2402 return find2 (0, 0, 0);
2405 const_iterator2 cbegin2 () const {
2409 const_iterator2 end2 () const {
2410 return find2 (0, 0, size2 ());
2413 const_iterator2 cend2 () const {
2417 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2419 public container_reference<hermitian_adaptor>,
2420 public random_access_iterator_base<typename iterator_restrict_traits<
2421 typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
2422 iterator2, value_type> {
2424 typedef typename subiterator2_type::value_type value_type;
2425 typedef typename subiterator2_type::difference_type difference_type;
2426 typedef typename subiterator2_type::reference reference;
2427 typedef typename subiterator2_type::pointer pointer;
2429 typedef iterator1 dual_iterator_type;
2430 typedef reverse_iterator1 dual_reverse_iterator_type;
2432 // Construction and destruction
2435 container_reference<self_type> (), it2_ () {}
2437 iterator2 (self_type &m, const subiterator2_type &it2):
2438 container_reference<self_type> (m), it2_ (it2) {}
2442 iterator2 &operator ++ () {
2447 iterator2 &operator -- () {
2452 iterator2 &operator += (difference_type n) {
2457 iterator2 &operator -= (difference_type n) {
2462 difference_type operator - (const iterator2 &it) const {
2463 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2464 return it2_ - it.it2_;
2469 reference operator * () const {
2473 reference operator [] (difference_type n) const {
2474 return *(*this + n);
2477 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2479 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2480 typename self_type::
2482 iterator1 begin () const {
2483 return (*this) ().find1 (1, 0, index2 ());
2486 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2487 typename self_type::
2489 iterator1 end () const {
2490 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
2493 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2494 typename self_type::
2496 reverse_iterator1 rbegin () const {
2497 return reverse_iterator1 (end ());
2500 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2501 typename self_type::
2503 reverse_iterator1 rend () const {
2504 return reverse_iterator1 (begin ());
2510 size_type index1 () const {
2511 return it2_.index1 ();
2514 size_type index2 () const {
2515 return it2_.index2 ();
2520 iterator2 &operator = (const iterator2 &it) {
2521 container_reference<self_type>::assign (&it ());
2528 bool operator == (const iterator2 &it) const {
2529 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2530 return it2_ == it.it2_;
2533 bool operator < (const iterator2 &it) const {
2534 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2535 return it2_ < it.it2_;
2539 subiterator2_type it2_;
2541 friend class const_iterator2;
2546 iterator2 begin2 () {
2547 return find2 (0, 0, 0);
2551 return find2 (0, 0, size2 ());
2554 // Reverse iterators
2557 const_reverse_iterator1 rbegin1 () const {
2558 return const_reverse_iterator1 (end1 ());
2561 const_reverse_iterator1 crbegin1 () const {
2565 const_reverse_iterator1 rend1 () const {
2566 return const_reverse_iterator1 (begin1 ());
2569 const_reverse_iterator1 crend1 () const {
2574 reverse_iterator1 rbegin1 () {
2575 return reverse_iterator1 (end1 ());
2578 reverse_iterator1 rend1 () {
2579 return reverse_iterator1 (begin1 ());
2583 const_reverse_iterator2 rbegin2 () const {
2584 return const_reverse_iterator2 (end2 ());
2587 const_reverse_iterator2 crbegin2 () const {
2591 const_reverse_iterator2 rend2 () const {
2592 return const_reverse_iterator2 (begin2 ());
2595 const_reverse_iterator2 crend2 () const {
2600 reverse_iterator2 rbegin2 () {
2601 return reverse_iterator2 (end2 ());
2604 reverse_iterator2 rend2 () {
2605 return reverse_iterator2 (begin2 ());
2609 matrix_closure_type data_;
2610 static value_type conj_;
2613 template<class M, class TRI>
2614 typename hermitian_adaptor<M, TRI>::value_type hermitian_adaptor<M, TRI>::conj_;
2616 // Specialization for temporary_traits
2617 template <class M, class TRI>
2618 struct vector_temporary_traits< hermitian_adaptor<M, TRI> >
2619 : vector_temporary_traits< M > {} ;
2620 template <class M, class TRI>
2621 struct vector_temporary_traits< const hermitian_adaptor<M, TRI> >
2622 : vector_temporary_traits< M > {} ;
2624 template <class M, class TRI>
2625 struct matrix_temporary_traits< hermitian_adaptor<M, TRI> >
2626 : matrix_temporary_traits< M > {} ;
2627 template <class M, class TRI>
2628 struct matrix_temporary_traits< const hermitian_adaptor<M, TRI> >
2629 : matrix_temporary_traits< M > {} ;