1//
2// Copyright (c) 2000-2010
3// Joerg Walter, Mathias Koch, David Bellot
4//
5// Distributed under the Boost Software License, Version 1.0. (See
6// accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9// The authors gratefully acknowledge the support of
10// GeNeSys mbH & Co. KG in producing this work.
11//
12
13#ifndef BOOST_UBLAS_HERMITIAN_H
14#define BOOST_UBLAS_HERMITIAN_H
15
16#include <boost/numeric/ublas/matrix.hpp>
17#include <boost/numeric/ublas/triangular.hpp> // for resize_preserve
18#include <boost/numeric/ublas/detail/temporary.hpp>
19
20// Iterators based on ideas of Jeremy Siek
21// Hermitian matrices are square. Thanks to Peter Schmitteckert for spotting this.
22
23namespace boost { namespace numeric { namespace ublas {
24
25 template<class M>
26 bool is_hermitian (const M &m) {
27 typedef typename M::size_type size_type;
28
29 if (m.size1 () != m.size2 ())
30 return false;
31 size_type size = BOOST_UBLAS_SAME (m.size1 (), m.size2 ());
32 for (size_type i = 0; i < size; ++ i) {
33 for (size_type j = i; j < size; ++ j) {
34 if (m (i, j) != conj (m (j, i)))
35 return false;
36 }
37 }
38 return true;
39 }
40
41#ifdef BOOST_UBLAS_STRICT_HERMITIAN
42
43 template<class M>
44 class hermitian_matrix_element:
45 public container_reference<M> {
46 public:
47 typedef M matrix_type;
48 typedef typename M::size_type size_type;
49 typedef typename M::value_type value_type;
50 typedef const value_type &const_reference;
51 typedef value_type &reference;
52 typedef value_type *pointer;
53
54 // Construction and destruction
55 BOOST_UBLAS_INLINE
56 hermitian_matrix_element (matrix_type &m, size_type i, size_type j, value_type d):
57 container_reference<matrix_type> (m), i_ (i), j_ (j), d_ (d), dirty_ (false) {}
58 BOOST_UBLAS_INLINE
59 ~hermitian_matrix_element () {
60 if (dirty_)
61 (*this) ().insert_element (i_, j_, d_);
62 }
63
64 // Assignment
65 BOOST_UBLAS_INLINE
66 hermitian_matrix_element &operator = (const hermitian_matrix_element &p) {
67 // Overide the implict copy assignment
68 d_ = p.d_;
69 dirty_ = true;
70 return *this;
71 }
72 template<class D>
73 BOOST_UBLAS_INLINE
74 hermitian_matrix_element &operator = (const D &d) {
75 d_ = d;
76 dirty_ = true;
77 return *this;
78 }
79 template<class D>
80 BOOST_UBLAS_INLINE
81 hermitian_matrix_element &operator += (const D &d) {
82 d_ += d;
83 dirty_ = true;
84 return *this;
85 }
86 template<class D>
87 BOOST_UBLAS_INLINE
88 hermitian_matrix_element &operator -= (const D &d) {
89 d_ -= d;
90 dirty_ = true;
91 return *this;
92 }
93 template<class D>
94 BOOST_UBLAS_INLINE
95 hermitian_matrix_element &operator *= (const D &d) {
96 d_ *= d;
97 dirty_ = true;
98 return *this;
99 }
100 template<class D>
101 BOOST_UBLAS_INLINE
102 hermitian_matrix_element &operator /= (const D &d) {
103 d_ /= d;
104 dirty_ = true;
105 return *this;
106 }
107
108 // Comparison
109 template<class D>
110 BOOST_UBLAS_INLINE
111 bool operator == (const D &d) const {
112 return d_ == d;
113 }
114 template<class D>
115 BOOST_UBLAS_INLINE
116 bool operator != (const D &d) const {
117 return d_ != d;
118 }
119
120 // Conversion
121 BOOST_UBLAS_INLINE
122 operator const_reference () const {
123 return d_;
124 }
125
126 // Swapping
127 BOOST_UBLAS_INLINE
128 void swap (hermitian_matrix_element p) {
129 if (this != &p) {
130 dirty_ = true;
131 p.dirty_ = true;
132 std::swap (d_, p.d_);
133 }
134 }
135 BOOST_UBLAS_INLINE
136 friend void swap (hermitian_matrix_element p1, hermitian_matrix_element p2) {
137 p1.swap (p2);
138 }
139
140 private:
141 size_type i_;
142 size_type j_;
143 value_type d_;
144 bool dirty_;
145 };
146
147 template<class M>
148 struct type_traits<hermitian_matrix_element<M> > {
149 typedef typename M::value_type element_type;
150 typedef type_traits<hermitian_matrix_element<M> > self_type;
151 typedef typename type_traits<element_type>::value_type value_type;
152 typedef typename type_traits<element_type>::const_reference const_reference;
153 typedef hermitian_matrix_element<M> reference;
154 typedef typename type_traits<element_type>::real_type real_type;
155 typedef typename type_traits<element_type>::precision_type precision_type;
156
157 static const unsigned plus_complexity = type_traits<element_type>::plus_complexity;
158 static const unsigned multiplies_complexity = type_traits<element_type>::multiplies_complexity;
159
160 static
161 BOOST_UBLAS_INLINE
162 real_type real (const_reference t) {
163 return type_traits<element_type>::real (t);
164 }
165 static
166 BOOST_UBLAS_INLINE
167 real_type imag (const_reference t) {
168 return type_traits<element_type>::imag (t);
169 }
170 static
171 BOOST_UBLAS_INLINE
172 value_type conj (const_reference t) {
173 return type_traits<element_type>::conj (t);
174 }
175
176 static
177 BOOST_UBLAS_INLINE
178 real_type type_abs (const_reference t) {
179 return type_traits<element_type>::type_abs (t);
180 }
181 static
182 BOOST_UBLAS_INLINE
183 value_type type_sqrt (const_reference t) {
184 return type_traits<element_type>::type_sqrt (t);
185 }
186
187 static
188 BOOST_UBLAS_INLINE
189 real_type norm_1 (const_reference t) {
190 return type_traits<element_type>::norm_1 (t);
191 }
192 static
193 BOOST_UBLAS_INLINE
194 real_type norm_2 (const_reference t) {
195 return type_traits<element_type>::norm_2 (t);
196 }
197 static
198 BOOST_UBLAS_INLINE
199 real_type norm_inf (const_reference t) {
200 return type_traits<element_type>::norm_inf (t);
201 }
202
203 static
204 BOOST_UBLAS_INLINE
205 bool equals (const_reference t1, const_reference t2) {
206 return type_traits<element_type>::equals (t1, t2);
207 }
208 };
209
210 template<class M1, class T2>
211 struct promote_traits<hermitian_matrix_element<M1>, T2> {
212 typedef typename promote_traits<typename hermitian_matrix_element<M1>::value_type, T2>::promote_type promote_type;
213 };
214 template<class T1, class M2>
215 struct promote_traits<T1, hermitian_matrix_element<M2> > {
216 typedef typename promote_traits<T1, typename hermitian_matrix_element<M2>::value_type>::promote_type promote_type;
217 };
218 template<class M1, class M2>
219 struct promote_traits<hermitian_matrix_element<M1>, hermitian_matrix_element<M2> > {
220 typedef typename promote_traits<typename hermitian_matrix_element<M1>::value_type,
221 typename hermitian_matrix_element<M2>::value_type>::promote_type promote_type;
222 };
223
224#endif
225 /** \brief A hermitian matrix of values of type \c T
226 *
227 * For a \f$(n \times n)\f$-dimensional matrix and \f$ 0 \leq i < n, 0 \leq j < n\f$, every element
228 * \f$m_{i,j}\f$ is mapped to the \f$(i.n + j)\f$-th element of the container for row major orientation
229 * or the \f$(i + j.m)\f$-th element of the container for column major orientation. And
230 * \f$\forall i,j\f$, \f$m_{i,j} = \overline{m_{i,j}}\f$.
231 *
232 * Orientation and storage can also be specified, otherwise a row major and unbounded array are used.
233 * It is \b not required by the storage to initialize elements of the matrix.
234 * Moreover, only the given triangular matrix is stored and the storage of hermitian matrices is packed.
235 *
236 * See http://en.wikipedia.org/wiki/Hermitian_matrix for more details on hermitian matrices.
237 *
238 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
239 * \tparam TRI the type of triangular matrix is either \c lower or \c upper. Default is \c lower
240 * \tparam L the storage organization. It is either \c row_major or \c column_major. Default is \c row_major
241 * \tparam A the type of Storage array. Default is \unbounded_array.
242 */
243 template<class T, class TRI, class L, class A>
244 class hermitian_matrix:
245 public matrix_container<hermitian_matrix<T, TRI, L, A> > {
246
247 typedef T &true_reference;
248 typedef T *pointer;
249 typedef TRI triangular_type;
250 typedef L layout_type;
251 typedef hermitian_matrix<T, TRI, L, A> self_type;
252 public:
253#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
254 using matrix_container<self_type>::operator ();
255#endif
256 typedef typename A::size_type size_type;
257 typedef typename A::difference_type difference_type;
258 typedef T value_type;
259 // FIXME no better way to not return the address of a temporary?
260 // typedef const T &const_reference;
261 typedef const T const_reference;
262#ifndef BOOST_UBLAS_STRICT_HERMITIAN
263 typedef T &reference;
264#else
265 typedef hermitian_matrix_element<self_type> reference;
266#endif
267 typedef A array_type;
268
269 typedef const matrix_reference<const self_type> const_closure_type;
270 typedef matrix_reference<self_type> closure_type;
271 typedef vector<T, A> vector_temporary_type;
272 typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix
273 typedef packed_tag storage_category;
274 typedef typename L::orientation_category orientation_category;
275
276 // Construction and destruction
277 BOOST_UBLAS_INLINE
278 hermitian_matrix ():
279 matrix_container<self_type> (),
280 size_ (0), data_ (0) {}
281 BOOST_UBLAS_INLINE
282 hermitian_matrix (size_type size):
283 matrix_container<self_type> (),
284 size_ (BOOST_UBLAS_SAME (size, size)), data_ (triangular_type::packed_size (layout_type (), size, size)) {
285 }
286 BOOST_UBLAS_INLINE
287 hermitian_matrix (size_type size1, size_type size2):
288 matrix_container<self_type> (),
289 size_ (BOOST_UBLAS_SAME (size1, size2)), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
290 }
291 BOOST_UBLAS_INLINE
292 hermitian_matrix (size_type size, const array_type &data):
293 matrix_container<self_type> (),
294 size_ (size), data_ (data) {}
295 BOOST_UBLAS_INLINE
296 hermitian_matrix (const hermitian_matrix &m):
297 matrix_container<self_type> (),
298 size_ (m.size_), data_ (m.data_) {}
299 template<class AE>
300 BOOST_UBLAS_INLINE
301 hermitian_matrix (const matrix_expression<AE> &ae):
302 matrix_container<self_type> (),
303 size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())),
304 data_ (triangular_type::packed_size (layout_type (), size_, size_)) {
305 matrix_assign<scalar_assign> (*this, ae);
306 }
307
308 // Accessors
309 BOOST_UBLAS_INLINE
310 size_type size1 () const {
311 return size_;
312 }
313 BOOST_UBLAS_INLINE
314 size_type size2 () const {
315 return size_;
316 }
317
318 // Storage accessors
319 BOOST_UBLAS_INLINE
320 const array_type &data () const {
321 return data_;
322 }
323 BOOST_UBLAS_INLINE
324 array_type &data () {
325 return data_;
326 }
327
328 // Resizing
329 BOOST_UBLAS_INLINE
330 void resize (size_type size, bool preserve = true) {
331 if (preserve) {
332 self_type temporary (size, size);
333 detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary);
334 }
335 else {
336 data ().resize (triangular_type::packed_size (layout_type (), size, size));
337 size_ = size;
338 }
339 }
340 BOOST_UBLAS_INLINE
341 void resize (size_type size1, size_type size2, bool preserve = true) {
342 resize (BOOST_UBLAS_SAME (size1, size2), preserve);
343 }
344 BOOST_UBLAS_INLINE
345 void resize_packed_preserve (size_type size) {
346 size_ = BOOST_UBLAS_SAME (size, size);
347 data ().resize (triangular_type::packed_size (layout_type (), size_, size_), value_type ());
348 }
349
350 // Element access
351 BOOST_UBLAS_INLINE
352 const_reference operator () (size_type i, size_type j) const {
353 BOOST_UBLAS_CHECK (i < size_, bad_index ());
354 BOOST_UBLAS_CHECK (j < size_, bad_index ());
355 // if (i == j)
356 // return type_traits<value_type>::real (data () [triangular_type::element (layout_type (), i, size_, i, size_)]);
357 // else
358 if (triangular_type::other (i, j))
359 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
360 else
361 return type_traits<value_type>::conj (data () [triangular_type::element (layout_type (), j, size_, i, size_)]);
362 }
363 BOOST_UBLAS_INLINE
364 true_reference at_element (size_type i, size_type j) {
365 BOOST_UBLAS_CHECK (i < size_, bad_index ());
366 BOOST_UBLAS_CHECK (j < size_, bad_index ());
367 BOOST_UBLAS_CHECK (triangular_type::other (i, j), bad_index ());
368 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
369 }
370 BOOST_UBLAS_INLINE
371 reference operator () (size_type i, size_type j) {
372#ifndef BOOST_UBLAS_STRICT_HERMITIAN
373 if (!triangular_type::other (i, j)) {
374 bad_index ().raise ();
375 // NEVER reached
376 }
377 return at_element (i, j);
378#else
379 if (triangular_type::other (i, j))
380 return reference (*this, i, j, data () [triangular_type::element (layout_type (), i, size_, j, size_)]);
381 else
382 return reference (*this, i, j, type_traits<value_type>::conj (data () [triangular_type::element (layout_type (), j, size_, i, size_)]));
383#endif
384 }
385
386 // Element assignemnt
387 BOOST_UBLAS_INLINE
388 true_reference insert_element (size_type i, size_type j, const_reference t) {
389 BOOST_UBLAS_CHECK (i < size_, bad_index ());
390 BOOST_UBLAS_CHECK (j < size_, bad_index ());
391 if (triangular_type::other (i, j)) {
392 return (data () [triangular_type::element (layout_type (), i, size_, j, size_)] = t);
393 } else {
394 return (data () [triangular_type::element (layout_type (), j, size_, i, size_)] = type_traits<value_type>::conj (t));
395 }
396 }
397 BOOST_UBLAS_INLINE
398 void erase_element (size_type i, size_type j) {
399 BOOST_UBLAS_CHECK (i < size_, bad_index ());
400 BOOST_UBLAS_CHECK (j < size_, bad_index ());
401 data () [triangular_type::element (layout_type (), i, size_, j, size_)] = value_type/*zero*/();
402 }
403
404 // Zeroing
405 BOOST_UBLAS_INLINE
406 void clear () {
407 std::fill (data ().begin (), data ().end (), value_type/*zero*/());
408 }
409
410 // Assignment
411 BOOST_UBLAS_INLINE
412 hermitian_matrix &operator = (const hermitian_matrix &m) {
413 size_ = m.size_;
414 data () = m.data ();
415 return *this;
416 }
417 BOOST_UBLAS_INLINE
418 hermitian_matrix &assign_temporary (hermitian_matrix &m) {
419 swap (m);
420 return *this;
421 }
422 template<class AE>
423 BOOST_UBLAS_INLINE
424 hermitian_matrix &operator = (const matrix_expression<AE> &ae) {
425 self_type temporary (ae);
426 return assign_temporary (m&: temporary);
427 }
428 template<class AE>
429 BOOST_UBLAS_INLINE
430 hermitian_matrix &assign (const matrix_expression<AE> &ae) {
431 matrix_assign<scalar_assign> (*this, ae);
432 return *this;
433 }
434 template<class AE>
435 BOOST_UBLAS_INLINE
436 hermitian_matrix& operator += (const matrix_expression<AE> &ae) {
437 self_type temporary (*this + ae);
438 return assign_temporary (m&: temporary);
439 }
440 template<class AE>
441 BOOST_UBLAS_INLINE
442 hermitian_matrix &plus_assign (const matrix_expression<AE> &ae) {
443 matrix_assign<scalar_plus_assign> (*this, ae);
444 return *this;
445 }
446 template<class AE>
447 BOOST_UBLAS_INLINE
448 hermitian_matrix& operator -= (const matrix_expression<AE> &ae) {
449 self_type temporary (*this - ae);
450 return assign_temporary (m&: temporary);
451 }
452 template<class AE>
453 BOOST_UBLAS_INLINE
454 hermitian_matrix &minus_assign (const matrix_expression<AE> &ae) {
455 matrix_assign<scalar_minus_assign> (*this, ae);
456 return *this;
457 }
458 template<class AT>
459 BOOST_UBLAS_INLINE
460 hermitian_matrix& operator *= (const AT &at) {
461 // Multiplication is only allowed for real scalars,
462 // otherwise the resulting matrix isn't hermitian.
463 // Thanks to Peter Schmitteckert for spotting this.
464 BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
465 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
466 return *this;
467 }
468 template<class AT>
469 BOOST_UBLAS_INLINE
470 hermitian_matrix& operator /= (const AT &at) {
471 // Multiplication is only allowed for real scalars,
472 // otherwise the resulting matrix isn't hermitian.
473 // Thanks to Peter Schmitteckert for spotting this.
474 BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
475 matrix_assign_scalar<scalar_divides_assign> (*this, at);
476 return *this;
477 }
478
479 // Swapping
480 BOOST_UBLAS_INLINE
481 void swap (hermitian_matrix &m) {
482 if (this != &m) {
483 std::swap (size_, m.size_);
484 data ().swap (m.data ());
485 }
486 }
487 BOOST_UBLAS_INLINE
488 friend void swap (hermitian_matrix &m1, hermitian_matrix &m2) {
489 m1.swap (m2);
490 }
491
492 // Iterator types
493#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
494 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
495 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
496 typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
497 typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
498#else
499 class const_iterator1;
500 class iterator1;
501 class const_iterator2;
502 class iterator2;
503#endif
504 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
505 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
506 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
507 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
508
509 // Element lookup
510 BOOST_UBLAS_INLINE
511 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
512 return const_iterator1 (*this, i, j);
513 }
514 BOOST_UBLAS_INLINE
515 iterator1 find1 (int rank, size_type i, size_type j) {
516 if (rank == 1)
517 i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
518 if (rank == 0)
519 i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
520 return iterator1 (*this, i, j);
521 }
522 BOOST_UBLAS_INLINE
523 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
524 return const_iterator2 (*this, i, j);
525 }
526 BOOST_UBLAS_INLINE
527 iterator2 find2 (int rank, size_type i, size_type j) {
528 if (rank == 1)
529 j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
530 if (rank == 0)
531 j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
532 return iterator2 (*this, i, j);
533 }
534
535 // Iterators simply are indices.
536
537#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
538 class const_iterator1:
539 public container_const_reference<hermitian_matrix>,
540 public random_access_iterator_base<packed_random_access_iterator_tag,
541 const_iterator1, value_type> {
542 public:
543 typedef typename hermitian_matrix::value_type value_type;
544 typedef typename hermitian_matrix::difference_type difference_type;
545 typedef typename hermitian_matrix::const_reference reference;
546 typedef const typename hermitian_matrix::pointer pointer;
547
548 typedef const_iterator2 dual_iterator_type;
549 typedef const_reverse_iterator2 dual_reverse_iterator_type;
550
551 // Construction and destruction
552 BOOST_UBLAS_INLINE
553 const_iterator1 ():
554 container_const_reference<self_type> (), it1_ (), it2_ () {}
555 BOOST_UBLAS_INLINE
556 const_iterator1 (const self_type &m, size_type it1, size_type it2):
557 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
558 BOOST_UBLAS_INLINE
559 const_iterator1 (const iterator1 &it):
560 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
561
562 // Arithmetic
563 BOOST_UBLAS_INLINE
564 const_iterator1 &operator ++ () {
565 ++ it1_;
566 return *this;
567 }
568 BOOST_UBLAS_INLINE
569 const_iterator1 &operator -- () {
570 -- it1_;
571 return *this;
572 }
573 BOOST_UBLAS_INLINE
574 const_iterator1 &operator += (difference_type n) {
575 it1_ += n;
576 return *this;
577 }
578 BOOST_UBLAS_INLINE
579 const_iterator1 &operator -= (difference_type n) {
580 it1_ -= n;
581 return *this;
582 }
583 BOOST_UBLAS_INLINE
584 difference_type operator - (const const_iterator1 &it) const {
585 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
586 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
587 return it1_ - it.it1_;
588 }
589
590 // Dereference
591 BOOST_UBLAS_INLINE
592 const_reference operator * () const {
593 return (*this) () (it1_, it2_);
594 }
595 BOOST_UBLAS_INLINE
596 const_reference operator [] (difference_type n) const {
597 return *(*this + n);
598 }
599
600#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
601 BOOST_UBLAS_INLINE
602#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
603 typename self_type::
604#endif
605 const_iterator2 begin () const {
606 return (*this) ().find2 (1, it1_, 0);
607 }
608 BOOST_UBLAS_INLINE
609#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
610 typename self_type::
611#endif
612 const_iterator2 cbegin () const {
613 return begin ();
614 }
615 BOOST_UBLAS_INLINE
616#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
617 typename self_type::
618#endif
619 const_iterator2 end () const {
620 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
621 }
622 BOOST_UBLAS_INLINE
623#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
624 typename self_type::
625#endif
626 const_iterator2 cend () const {
627 return end ();
628 }
629 BOOST_UBLAS_INLINE
630#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
631 typename self_type::
632#endif
633 const_reverse_iterator2 rbegin () const {
634 return const_reverse_iterator2 (end ());
635 }
636 BOOST_UBLAS_INLINE
637#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
638 typename self_type::
639#endif
640 const_reverse_iterator2 crbegin () const {
641 return rbegin ();
642 }
643 BOOST_UBLAS_INLINE
644#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
645 typename self_type::
646#endif
647 const_reverse_iterator2 rend () const {
648 return const_reverse_iterator2 (begin ());
649 }
650 BOOST_UBLAS_INLINE
651#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
652 typename self_type::
653#endif
654 const_reverse_iterator2 crend () const {
655 return rend ();
656 }
657#endif
658
659 // Indices
660 BOOST_UBLAS_INLINE
661 size_type index1 () const {
662 return it1_;
663 }
664 BOOST_UBLAS_INLINE
665 size_type index2 () const {
666 return it2_;
667 }
668
669 // Assignment
670 BOOST_UBLAS_INLINE
671 const_iterator1 &operator = (const const_iterator1 &it) {
672 container_const_reference<self_type>::assign (&it ());
673 it1_ = it.it1_;
674 it2_ = it.it2_;
675 return *this;
676 }
677
678 // Comparison
679 BOOST_UBLAS_INLINE
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_;
684 }
685 BOOST_UBLAS_INLINE
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_;
690 }
691
692 private:
693 size_type it1_;
694 size_type it2_;
695 };
696#endif
697
698 BOOST_UBLAS_INLINE
699 const_iterator1 begin1 () const {
700 return find1 (0, 0, 0);
701 }
702 BOOST_UBLAS_INLINE
703 const_iterator1 cbegin1 () const {
704 return begin1 ();
705 }
706 BOOST_UBLAS_INLINE
707 const_iterator1 end1 () const {
708 return find1 (0, size_, 0);
709 }
710 BOOST_UBLAS_INLINE
711 const_iterator1 cend1 () const {
712 return end1 ();
713 }
714
715#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
716 class iterator1:
717 public container_reference<hermitian_matrix>,
718 public random_access_iterator_base<packed_random_access_iterator_tag,
719 iterator1, value_type> {
720 public:
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;
725
726 typedef iterator2 dual_iterator_type;
727 typedef reverse_iterator2 dual_reverse_iterator_type;
728
729 // Construction and destruction
730 BOOST_UBLAS_INLINE
731 iterator1 ():
732 container_reference<self_type> (), it1_ (), it2_ () {}
733 BOOST_UBLAS_INLINE
734 iterator1 (self_type &m, size_type it1, size_type it2):
735 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
736
737 // Arithmetic
738 BOOST_UBLAS_INLINE
739 iterator1 &operator ++ () {
740 ++ it1_;
741 return *this;
742 }
743 BOOST_UBLAS_INLINE
744 iterator1 &operator -- () {
745 -- it1_;
746 return *this;
747 }
748 BOOST_UBLAS_INLINE
749 iterator1 &operator += (difference_type n) {
750 it1_ += n;
751 return *this;
752 }
753 BOOST_UBLAS_INLINE
754 iterator1 &operator -= (difference_type n) {
755 it1_ -= n;
756 return *this;
757 }
758 BOOST_UBLAS_INLINE
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_;
763 }
764
765 // Dereference
766 BOOST_UBLAS_INLINE
767 reference operator * () const {
768 return (*this) ().at_element (it1_, it2_);
769 }
770 BOOST_UBLAS_INLINE
771 reference operator [] (difference_type n) const {
772 return *(*this + n);
773 }
774
775#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
776 BOOST_UBLAS_INLINE
777#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
778 typename self_type::
779#endif
780 iterator2 begin () const {
781 return (*this) ().find2 (1, it1_, 0);
782 }
783 BOOST_UBLAS_INLINE
784#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
785 typename self_type::
786#endif
787 iterator2 end () const {
788 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
789 }
790 BOOST_UBLAS_INLINE
791#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
792 typename self_type::
793#endif
794 reverse_iterator2 rbegin () const {
795 return reverse_iterator2 (end ());
796 }
797 BOOST_UBLAS_INLINE
798#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
799 typename self_type::
800#endif
801 reverse_iterator2 rend () const {
802 return reverse_iterator2 (begin ());
803 }
804#endif
805
806 // Indices
807 BOOST_UBLAS_INLINE
808 size_type index1 () const {
809 return it1_;
810 }
811 BOOST_UBLAS_INLINE
812 size_type index2 () const {
813 return it2_;
814 }
815
816 // Assignment
817 BOOST_UBLAS_INLINE
818 iterator1 &operator = (const iterator1 &it) {
819 container_reference<self_type>::assign (&it ());
820 it1_ = it.it1_;
821 it2_ = it.it2_;
822 return *this;
823 }
824
825 // Comparison
826 BOOST_UBLAS_INLINE
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_;
831 }
832 BOOST_UBLAS_INLINE
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_;
837 }
838
839 private:
840 size_type it1_;
841 size_type it2_;
842
843 friend class const_iterator1;
844 };
845#endif
846
847 BOOST_UBLAS_INLINE
848 iterator1 begin1 () {
849 return find1 (0, 0, 0);
850 }
851 BOOST_UBLAS_INLINE
852 iterator1 end1 () {
853 return find1 (0, size_, 0);
854 }
855
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> {
861 public:
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;
866
867 typedef const_iterator1 dual_iterator_type;
868 typedef const_reverse_iterator1 dual_reverse_iterator_type;
869
870 // Construction and destruction
871 BOOST_UBLAS_INLINE
872 const_iterator2 ():
873 container_const_reference<self_type> (), it1_ (), it2_ () {}
874 BOOST_UBLAS_INLINE
875 const_iterator2 (const self_type &m, size_type it1, size_type it2):
876 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
877 BOOST_UBLAS_INLINE
878 const_iterator2 (const iterator2 &it):
879 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
880
881 // Arithmetic
882 BOOST_UBLAS_INLINE
883 const_iterator2 &operator ++ () {
884 ++ it2_;
885 return *this;
886 }
887 BOOST_UBLAS_INLINE
888 const_iterator2 &operator -- () {
889 -- it2_;
890 return *this;
891 }
892 BOOST_UBLAS_INLINE
893 const_iterator2 &operator += (difference_type n) {
894 it2_ += n;
895 return *this;
896 }
897 BOOST_UBLAS_INLINE
898 const_iterator2 &operator -= (difference_type n) {
899 it2_ -= n;
900 return *this;
901 }
902 BOOST_UBLAS_INLINE
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_;
907 }
908
909 // Dereference
910 BOOST_UBLAS_INLINE
911 const_reference operator * () const {
912 return (*this) () (it1_, it2_);
913 }
914 BOOST_UBLAS_INLINE
915 const_reference operator [] (difference_type n) const {
916 return *(*this + n);
917 }
918
919#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
920 BOOST_UBLAS_INLINE
921#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
922 typename self_type::
923#endif
924 const_iterator1 begin () const {
925 return (*this) ().find1 (1, 0, it2_);
926 }
927 BOOST_UBLAS_INLINE
928#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
929 typename self_type::
930#endif
931 const_iterator1 cbegin () const {
932 return begin ();
933 }
934 BOOST_UBLAS_INLINE
935#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
936 typename self_type::
937#endif
938 const_iterator1 end () const {
939 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
940 }
941 BOOST_UBLAS_INLINE
942#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
943 typename self_type::
944#endif
945 const_iterator1 cend () const {
946 return end ();
947 }
948 BOOST_UBLAS_INLINE
949#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
950 typename self_type::
951#endif
952 const_reverse_iterator1 rbegin () const {
953 return const_reverse_iterator1 (end ());
954 }
955 BOOST_UBLAS_INLINE
956#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
957 typename self_type::
958#endif
959 const_iterator1 crbegin () const {
960 return rbegin ();
961 }
962 BOOST_UBLAS_INLINE
963#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
964 typename self_type::
965#endif
966 const_reverse_iterator1 rend () const {
967 return const_reverse_iterator1 (begin ());
968 }
969 BOOST_UBLAS_INLINE
970#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
971 typename self_type::
972#endif
973 const_iterator1 crend () const {
974 return rend ();
975 }
976#endif
977
978 // Indices
979 BOOST_UBLAS_INLINE
980 size_type index1 () const {
981 return it1_;
982 }
983 BOOST_UBLAS_INLINE
984 size_type index2 () const {
985 return it2_;
986 }
987
988 // Assignment
989 BOOST_UBLAS_INLINE
990 const_iterator2 &operator = (const const_iterator2 &it) {
991 container_const_reference<self_type>::assign (&it ());
992 it1_ = it.it1_;
993 it2_ = it.it2_;
994 return *this;
995 }
996
997 // Comparison
998 BOOST_UBLAS_INLINE
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_;
1003 }
1004 BOOST_UBLAS_INLINE
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_;
1009 }
1010
1011 private:
1012 size_type it1_;
1013 size_type it2_;
1014 };
1015#endif
1016
1017 BOOST_UBLAS_INLINE
1018 const_iterator2 begin2 () const {
1019 return find2 (0, 0, 0);
1020 }
1021 BOOST_UBLAS_INLINE
1022 const_iterator2 cbegin2 () const {
1023 return begin2 ();
1024 }
1025 BOOST_UBLAS_INLINE
1026 const_iterator2 end2 () const {
1027 return find2 (0, 0, size_);
1028 }
1029 BOOST_UBLAS_INLINE
1030 const_iterator2 cend2 () const {
1031 return end2 ();
1032 }
1033
1034#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1035 class iterator2:
1036 public container_reference<hermitian_matrix>,
1037 public random_access_iterator_base<packed_random_access_iterator_tag,
1038 iterator2, value_type> {
1039 public:
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;
1044
1045 typedef iterator1 dual_iterator_type;
1046 typedef reverse_iterator1 dual_reverse_iterator_type;
1047
1048 // Construction and destruction
1049 BOOST_UBLAS_INLINE
1050 iterator2 ():
1051 container_reference<self_type> (), it1_ (), it2_ () {}
1052 BOOST_UBLAS_INLINE
1053 iterator2 (self_type &m, size_type it1, size_type it2):
1054 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
1055
1056 // Arithmetic
1057 BOOST_UBLAS_INLINE
1058 iterator2 &operator ++ () {
1059 ++ it2_;
1060 return *this;
1061 }
1062 BOOST_UBLAS_INLINE
1063 iterator2 &operator -- () {
1064 -- it2_;
1065 return *this;
1066 }
1067 BOOST_UBLAS_INLINE
1068 iterator2 &operator += (difference_type n) {
1069 it2_ += n;
1070 return *this;
1071 }
1072 BOOST_UBLAS_INLINE
1073 iterator2 &operator -= (difference_type n) {
1074 it2_ -= n;
1075 return *this;
1076 }
1077 BOOST_UBLAS_INLINE
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_;
1082 }
1083
1084 // Dereference
1085 BOOST_UBLAS_INLINE
1086 reference operator * () const {
1087 return (*this) ().at_element (it1_, it2_);
1088 }
1089 BOOST_UBLAS_INLINE
1090 reference operator [] (difference_type n) const {
1091 return *(*this + n);
1092 }
1093
1094#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1095 BOOST_UBLAS_INLINE
1096#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1097 typename self_type::
1098#endif
1099 iterator1 begin () const {
1100 return (*this) ().find1 (1, 0, it2_);
1101 }
1102 BOOST_UBLAS_INLINE
1103#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1104 typename self_type::
1105#endif
1106 iterator1 end () const {
1107 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
1108 }
1109 BOOST_UBLAS_INLINE
1110#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1111 typename self_type::
1112#endif
1113 reverse_iterator1 rbegin () const {
1114 return reverse_iterator1 (end ());
1115 }
1116 BOOST_UBLAS_INLINE
1117#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1118 typename self_type::
1119#endif
1120 reverse_iterator1 rend () const {
1121 return reverse_iterator1 (begin ());
1122 }
1123#endif
1124
1125 // Indices
1126 BOOST_UBLAS_INLINE
1127 size_type index1 () const {
1128 return it1_;
1129 }
1130 BOOST_UBLAS_INLINE
1131 size_type index2 () const {
1132 return it2_;
1133 }
1134
1135 // Assignment
1136 BOOST_UBLAS_INLINE
1137 iterator2 &operator = (const iterator2 &it) {
1138 container_reference<self_type>::assign (&it ());
1139 it1_ = it.it1_;
1140 it2_ = it.it2_;
1141 return *this;
1142 }
1143
1144 // Comparison
1145 BOOST_UBLAS_INLINE
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_;
1150 }
1151 BOOST_UBLAS_INLINE
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_;
1156 }
1157
1158 private:
1159 size_type it1_;
1160 size_type it2_;
1161
1162 friend class const_iterator2;
1163 };
1164#endif
1165
1166 BOOST_UBLAS_INLINE
1167 iterator2 begin2 () {
1168 return find2 (0, 0, 0);
1169 }
1170 BOOST_UBLAS_INLINE
1171 iterator2 end2 () {
1172 return find2 (0, 0, size_);
1173 }
1174
1175 // Reverse iterators
1176
1177 BOOST_UBLAS_INLINE
1178 const_reverse_iterator1 rbegin1 () const {
1179 return const_reverse_iterator1 (end1 ());
1180 }
1181 BOOST_UBLAS_INLINE
1182 const_reverse_iterator1 crbegin1 () const {
1183 return rbegin1 ();
1184 }
1185 BOOST_UBLAS_INLINE
1186 const_reverse_iterator1 rend1 () const {
1187 return const_reverse_iterator1 (begin1 ());
1188 }
1189 BOOST_UBLAS_INLINE
1190 const_reverse_iterator1 crend1 () const {
1191 return rend1 ();
1192 }
1193
1194 BOOST_UBLAS_INLINE
1195 reverse_iterator1 rbegin1 () {
1196 return reverse_iterator1 (end1 ());
1197 }
1198 BOOST_UBLAS_INLINE
1199 reverse_iterator1 rend1 () {
1200 return reverse_iterator1 (begin1 ());
1201 }
1202
1203 BOOST_UBLAS_INLINE
1204 const_reverse_iterator2 rbegin2 () const {
1205 return const_reverse_iterator2 (end2 ());
1206 }
1207 BOOST_UBLAS_INLINE
1208 const_reverse_iterator2 crbegin2 () const {
1209 return rbegin2();
1210 }
1211 BOOST_UBLAS_INLINE
1212 const_reverse_iterator2 rend2 () const {
1213 return const_reverse_iterator2 (begin2 ());
1214 }
1215 BOOST_UBLAS_INLINE
1216 const_reverse_iterator2 crend2 () const {
1217 return rend2 ();
1218 }
1219
1220 BOOST_UBLAS_INLINE
1221 reverse_iterator2 rbegin2 () {
1222 return reverse_iterator2 (end2 ());
1223 }
1224 BOOST_UBLAS_INLINE
1225 reverse_iterator2 rend2 () {
1226 return reverse_iterator2 (begin2 ());
1227 }
1228
1229 private:
1230 size_type size_;
1231 array_type data_;
1232 };
1233
1234 /** \brief A Hermitian matrix adaptator: convert a any matrix into a Hermitian matrix expression
1235 *
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.
1240 *
1241 * \tparam M the type of matrix used to generate a hermitian matrix
1242 */
1243 template<class M, class TRI>
1244 class hermitian_adaptor:
1245 public matrix_expression<hermitian_adaptor<M, TRI> > {
1246
1247 typedef hermitian_adaptor<M, TRI> self_type;
1248 typedef typename M::value_type &true_reference;
1249 public:
1250#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1251 using matrix_expression<self_type>::operator ();
1252#endif
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;
1264#else
1265 typedef typename boost::mpl::if_<boost::is_const<M>,
1266 typename M::value_type,
1267 hermitian_matrix_element<self_type> >::type reference;
1268#endif
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;
1280
1281 // Construction and destruction
1282 BOOST_UBLAS_INLINE
1283 hermitian_adaptor (matrix_type &data):
1284 matrix_expression<self_type> (),
1285 data_ (data) {
1286 BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
1287 }
1288 BOOST_UBLAS_INLINE
1289 hermitian_adaptor (const hermitian_adaptor &m):
1290 matrix_expression<self_type> (),
1291 data_ (m.data_) {
1292 BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
1293 }
1294
1295 // Accessors
1296 BOOST_UBLAS_INLINE
1297 size_type size1 () const {
1298 return data_.size1 ();
1299 }
1300 BOOST_UBLAS_INLINE
1301 size_type size2 () const {
1302 return data_.size2 ();
1303 }
1304
1305 // Storage accessors
1306 BOOST_UBLAS_INLINE
1307 const matrix_closure_type &data () const {
1308 return data_;
1309 }
1310 BOOST_UBLAS_INLINE
1311 matrix_closure_type &data () {
1312 return data_;
1313 }
1314
1315 // Element access
1316#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1317 BOOST_UBLAS_INLINE
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 ());
1321 // if (i == j)
1322 // return type_traits<value_type>::real (data () (i, i));
1323 // else
1324 if (triangular_type::other (i, j))
1325 return data () (i, j);
1326 else
1327 return type_traits<value_type>::conj (data () (j, i));
1328 }
1329 BOOST_UBLAS_INLINE
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);
1336 else {
1337 external_logic ().raise ();
1338 return conj_ = type_traits<value_type>::conj (data () (j, i));
1339 }
1340#else
1341 if (triangular_type::other (i, j))
1342 return reference (*this, i, j, data () (i, j));
1343 else
1344 return reference (*this, i, j, type_traits<value_type>::conj (data () (j, i)));
1345#endif
1346 }
1347 BOOST_UBLAS_INLINE
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 ());
1351 // if (i == j)
1352 // data () (i, i) = type_traits<value_type>::real (t);
1353 // else
1354 if (triangular_type::other (i, j))
1355 return data () (i, j) = t;
1356 else
1357 return data () (j, i) = type_traits<value_type>::conj (t);
1358 }
1359#else
1360 BOOST_UBLAS_INLINE
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);
1367 else {
1368 external_logic ().raise ();
1369 return conj_ = type_traits<value_type>::conj (data () (j, i));
1370 }
1371#else
1372 if (triangular_type::other (i, j))
1373 return reference (*this, i, j, data () (i, j));
1374 else
1375 return reference (*this, i, j, type_traits<value_type>::conj (data () (j, i)));
1376#endif
1377 }
1378 BOOST_UBLAS_INLINE
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 ());
1382 // if (i == j)
1383 // data () (i, i) = type_traits<value_type>::real (t);
1384 // else
1385 if (triangular_type::other (i, j))
1386 return data () (i, j) = t;
1387 else
1388 return data () (j, i) = type_traits<value_type>::conj (t);
1389 }
1390#endif
1391
1392 // Assignment
1393 BOOST_UBLAS_INLINE
1394 hermitian_adaptor &operator = (const hermitian_adaptor &m) {
1395 matrix_assign<scalar_assign, triangular_type> (*this, m);
1396 return *this;
1397 }
1398 BOOST_UBLAS_INLINE
1399 hermitian_adaptor &assign_temporary (hermitian_adaptor &m) {
1400 *this = m;
1401 return *this;
1402 }
1403 template<class AE>
1404 BOOST_UBLAS_INLINE
1405 hermitian_adaptor &operator = (const matrix_expression<AE> &ae) {
1406 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae));
1407 return *this;
1408 }
1409 template<class AE>
1410 BOOST_UBLAS_INLINE
1411 hermitian_adaptor &assign (const matrix_expression<AE> &ae) {
1412 matrix_assign<scalar_assign, triangular_type> (*this, ae);
1413 return *this;
1414 }
1415 template<class AE>
1416 BOOST_UBLAS_INLINE
1417 hermitian_adaptor& operator += (const matrix_expression<AE> &ae) {
1418 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae));
1419 return *this;
1420 }
1421 template<class AE>
1422 BOOST_UBLAS_INLINE
1423 hermitian_adaptor &plus_assign (const matrix_expression<AE> &ae) {
1424 matrix_assign<scalar_plus_assign, triangular_type> (*this, ae);
1425 return *this;
1426 }
1427 template<class AE>
1428 BOOST_UBLAS_INLINE
1429 hermitian_adaptor& operator -= (const matrix_expression<AE> &ae) {
1430 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae));
1431 return *this;
1432 }
1433 template<class AE>
1434 BOOST_UBLAS_INLINE
1435 hermitian_adaptor &minus_assign (const matrix_expression<AE> &ae) {
1436 matrix_assign<scalar_minus_assign, triangular_type> (*this, ae);
1437 return *this;
1438 }
1439 template<class AT>
1440 BOOST_UBLAS_INLINE
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);
1447 return *this;
1448 }
1449 template<class AT>
1450 BOOST_UBLAS_INLINE
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);
1457 return *this;
1458 }
1459
1460 // Closure comparison
1461 BOOST_UBLAS_INLINE
1462 bool same_closure (const hermitian_adaptor &ha) const {
1463 return (*this).data ().same_closure (ha.data ());
1464 }
1465
1466 // Swapping
1467 BOOST_UBLAS_INLINE
1468 void swap (hermitian_adaptor &m) {
1469 if (this != &m)
1470 matrix_swap<scalar_swap, triangular_type> (*this, m);
1471 }
1472 BOOST_UBLAS_INLINE
1473 friend void swap (hermitian_adaptor &m1, hermitian_adaptor &m2) {
1474 m1.swap (m2);
1475 }
1476
1477 // Iterator types
1478 private:
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;
1488
1489 public:
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;
1495#else
1496 class const_iterator1;
1497 class iterator1;
1498 class const_iterator2;
1499 class iterator2;
1500#endif
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;
1505
1506 // Element lookup
1507 BOOST_UBLAS_INLINE
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 ()));
1514 } else {
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 ()));
1518 }
1519 } else {
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));
1524 } else {
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 ()));
1528 }
1529 }
1530 }
1531 BOOST_UBLAS_INLINE
1532 iterator1 find1 (int rank, size_type i, size_type j) {
1533 if (rank == 1)
1534 i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
1535 if (rank == 0)
1536 i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
1537 return iterator1 (*this, data ().find1 (rank, i, j));
1538 }
1539 BOOST_UBLAS_INLINE
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 ()));
1546 } else {
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));
1550 }
1551 } else {
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 ()));
1556 } else {
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 ()));
1560 }
1561 }
1562 }
1563 BOOST_UBLAS_INLINE
1564 iterator2 find2 (int rank, size_type i, size_type j) {
1565 if (rank == 1)
1566 j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
1567 if (rank == 0)
1568 j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
1569 return iterator2 (*this, data ().find2 (rank, i, j));
1570 }
1571
1572 // Iterators simply are indices.
1573
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> {
1580 public:
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;
1587
1588 typedef const_iterator2 dual_iterator_type;
1589 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1590
1591 // Construction and destruction
1592 BOOST_UBLAS_INLINE
1593 const_iterator1 ():
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_ () {}
1598 BOOST_UBLAS_INLINE
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_)
1607 current_ = 1;
1608 if (current_ == 1 && it2_ == it2_end_)
1609 current_ = 0;
1610 if ((current_ == 0 && it1_ == it1_end_) ||
1611 (current_ == 1 && it2_ == it2_end_))
1612 current_ = end_;
1613 BOOST_UBLAS_CHECK (current_ == end_ ||
1614 (current_ == 0 && it1_ != it1_end_) ||
1615 (current_ == 1 && it2_ != it2_end_), internal_logic ());
1616 }
1617 // FIXME cannot compile
1618 // iterator1 does not have these members!
1619 BOOST_UBLAS_INLINE
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 ());
1628 }
1629
1630 // Arithmetic
1631 BOOST_UBLAS_INLINE
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 ());
1636 ++ it1_;
1637 if (it1_ == it1_end_ && end_ == 1) {
1638 it2_ = it2_begin_;
1639 current_ = 1;
1640 }
1641 } else /* if (current_ == 1) */ {
1642 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1643 ++ it2_;
1644 if (it2_ == it2_end_ && end_ == 0) {
1645 it1_ = it1_begin_;
1646 current_ = 0;
1647 }
1648 }
1649 return *this;
1650 }
1651 BOOST_UBLAS_INLINE
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) {
1656 it2_ = it2_end_;
1657 BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
1658 -- it2_;
1659 current_ = 1;
1660 } else {
1661 -- it1_;
1662 }
1663 } else /* if (current_ == 1) */ {
1664 if (it2_ == it2_begin_ && begin_ == 0) {
1665 it1_ = it1_end_;
1666 BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
1667 -- it1_;
1668 current_ = 0;
1669 } else {
1670 -- it2_;
1671 }
1672 }
1673 return *this;
1674 }
1675 BOOST_UBLAS_INLINE
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_);
1680 it1_ += d;
1681 n -= d;
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;
1686 n -= d;
1687 current_ = 1;
1688 }
1689 } else /* if (current_ == 1) */ {
1690 size_type d = (std::min) (n, it2_end_ - it2_);
1691 it2_ += d;
1692 n -= d;
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;
1697 n -= d;
1698 current_ = 0;
1699 }
1700 }
1701 BOOST_UBLAS_CHECK (n == 0, external_logic ());
1702 return *this;
1703 }
1704 BOOST_UBLAS_INLINE
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_);
1709 it1_ -= d;
1710 n -= d;
1711 if (n > 0) {
1712 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1713 d = (std::min) (n, it2_end_ - it2_begin_);
1714 it2_ = it2_end_ - d;
1715 n -= d;
1716 current_ = 1;
1717 }
1718 } else /* if (current_ == 1) */ {
1719 size_type d = (std::min) (n, it2_ - it2_begin_);
1720 it2_ -= d;
1721 n -= d;
1722 if (n > 0) {
1723 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1724 d = (std::min) (n, it1_end_ - it1_begin_);
1725 it1_ = it1_end_ - d;
1726 n -= d;
1727 current_ = 0;
1728 }
1729 }
1730 BOOST_UBLAS_CHECK (n == 0, external_logic ());
1731 return *this;
1732 }
1733 BOOST_UBLAS_INLINE
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_);
1746 }
1747
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_);
1753 }
1754 } else /* if (current_ == 1 && it.current_ == 1) */ {
1755 return it2_ - it.it2_;
1756 }
1757 }
1758
1759 // Dereference
1760 BOOST_UBLAS_INLINE
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 ()))
1766 return *it1_;
1767 else
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 ()))
1772 return *it2_;
1773 else
1774 return type_traits<value_type>::conj (*it2_);
1775 }
1776 }
1777 BOOST_UBLAS_INLINE
1778 const_reference operator [] (difference_type n) const {
1779 return *(*this + n);
1780 }
1781
1782#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1783 BOOST_UBLAS_INLINE
1784#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1785 typename self_type::
1786#endif
1787 const_iterator2 begin () const {
1788 return (*this) ().find2 (1, index1 (), 0);
1789 }
1790 BOOST_UBLAS_INLINE
1791#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1792 typename self_type::
1793#endif
1794 const_iterator2 cbegin () const {
1795 return begin ();
1796 }
1797 BOOST_UBLAS_INLINE
1798#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1799 typename self_type::
1800#endif
1801 const_iterator2 end () const {
1802 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1803 }
1804 BOOST_UBLAS_INLINE
1805#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1806 typename self_type::
1807#endif
1808 const_iterator2 cend () const {
1809 return end ();
1810 }
1811 BOOST_UBLAS_INLINE
1812#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1813 typename self_type::
1814#endif
1815 const_reverse_iterator2 rbegin () const {
1816 return const_reverse_iterator2 (end ());
1817 }
1818 BOOST_UBLAS_INLINE
1819#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1820 typename self_type::
1821#endif
1822 const_reverse_iterator2 crbegin () const {
1823 return rbegin ();
1824 }
1825 BOOST_UBLAS_INLINE
1826#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1827 typename self_type::
1828#endif
1829 const_reverse_iterator2 rend () const {
1830 return const_reverse_iterator2 (begin ());
1831 }
1832 BOOST_UBLAS_INLINE
1833#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1834 typename self_type::
1835#endif
1836 const_reverse_iterator2 crend () const {
1837 return rend ();
1838 }
1839#endif
1840
1841 // Indices
1842 BOOST_UBLAS_INLINE
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 ();
1851 }
1852 }
1853 BOOST_UBLAS_INLINE
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 ();
1862 }
1863 }
1864
1865 // Assignment
1866 BOOST_UBLAS_INLINE
1867 const_iterator1 &operator = (const const_iterator1 &it) {
1868 container_const_reference<self_type>::assign (&it ());
1869 begin_ = it.begin_;
1870 end_ = it.end_;
1871 current_ = it.current_;
1872 it1_begin_ = it.it1_begin_;
1873 it1_end_ = it.it1_end_;
1874 it1_ = it.it1_;
1875 it2_begin_ = it.it2_begin_;
1876 it2_end_ = it.it2_end_;
1877 it2_ = it.it2_;
1878 return *this;
1879 }
1880
1881 // Comparison
1882 BOOST_UBLAS_INLINE
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_);
1890 }
1891 BOOST_UBLAS_INLINE
1892 bool operator < (const const_iterator1 &it) const {
1893 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1894 return it - *this > 0;
1895 }
1896
1897 private:
1898 int begin_;
1899 int end_;
1900 int current_;
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_;
1907 };
1908#endif
1909
1910 BOOST_UBLAS_INLINE
1911 const_iterator1 begin1 () const {
1912 return find1 (0, 0, 0);
1913 }
1914 BOOST_UBLAS_INLINE
1915 const_iterator1 cbegin1 () const {
1916 return begin1 ();
1917 }
1918 BOOST_UBLAS_INLINE
1919 const_iterator1 end1 () const {
1920 return find1 (0, size1 (), 0);
1921 }
1922 BOOST_UBLAS_INLINE
1923 const_iterator1 cend1 () const {
1924 return end1 ();
1925 }
1926
1927#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1928 class iterator1:
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> {
1933 public:
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;
1938
1939 typedef iterator2 dual_iterator_type;
1940 typedef reverse_iterator2 dual_reverse_iterator_type;
1941
1942 // Construction and destruction
1943 BOOST_UBLAS_INLINE
1944 iterator1 ():
1945 container_reference<self_type> (), it1_ () {}
1946 BOOST_UBLAS_INLINE
1947 iterator1 (self_type &m, const subiterator1_type &it1):
1948 container_reference<self_type> (m), it1_ (it1) {}
1949
1950 // Arithmetic
1951 BOOST_UBLAS_INLINE
1952 iterator1 &operator ++ () {
1953 ++ it1_;
1954 return *this;
1955 }
1956 BOOST_UBLAS_INLINE
1957 iterator1 &operator -- () {
1958 -- it1_;
1959 return *this;
1960 }
1961 BOOST_UBLAS_INLINE
1962 iterator1 &operator += (difference_type n) {
1963 it1_ += n;
1964 return *this;
1965 }
1966 BOOST_UBLAS_INLINE
1967 iterator1 &operator -= (difference_type n) {
1968 it1_ -= n;
1969 return *this;
1970 }
1971 BOOST_UBLAS_INLINE
1972 difference_type operator - (const iterator1 &it) const {
1973 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1974 return it1_ - it.it1_;
1975 }
1976
1977 // Dereference
1978 BOOST_UBLAS_INLINE
1979 reference operator * () const {
1980 return *it1_;
1981 }
1982 BOOST_UBLAS_INLINE
1983 reference operator [] (difference_type n) const {
1984 return *(*this + n);
1985 }
1986
1987#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1988 BOOST_UBLAS_INLINE
1989#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1990 typename self_type::
1991#endif
1992 iterator2 begin () const {
1993 return (*this) ().find2 (1, index1 (), 0);
1994 }
1995 BOOST_UBLAS_INLINE
1996#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1997 typename self_type::
1998#endif
1999 iterator2 end () const {
2000 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
2001 }
2002 BOOST_UBLAS_INLINE
2003#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2004 typename self_type::
2005#endif
2006 reverse_iterator2 rbegin () const {
2007 return reverse_iterator2 (end ());
2008 }
2009 BOOST_UBLAS_INLINE
2010#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2011 typename self_type::
2012#endif
2013 reverse_iterator2 rend () const {
2014 return reverse_iterator2 (begin ());
2015 }
2016#endif
2017
2018 // Indices
2019 BOOST_UBLAS_INLINE
2020 size_type index1 () const {
2021 return it1_.index1 ();
2022 }
2023 BOOST_UBLAS_INLINE
2024 size_type index2 () const {
2025 return it1_.index2 ();
2026 }
2027
2028 // Assignment
2029 BOOST_UBLAS_INLINE
2030 iterator1 &operator = (const iterator1 &it) {
2031 container_reference<self_type>::assign (&it ());
2032 it1_ = it.it1_;
2033 return *this;
2034 }
2035
2036 // Comparison
2037 BOOST_UBLAS_INLINE
2038 bool operator == (const iterator1 &it) const {
2039 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2040 return it1_ == it.it1_;
2041 }
2042 BOOST_UBLAS_INLINE
2043 bool operator < (const iterator1 &it) const {
2044 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2045 return it1_ < it.it1_;
2046 }
2047
2048 private:
2049 subiterator1_type it1_;
2050
2051 friend class const_iterator1;
2052 };
2053#endif
2054
2055 BOOST_UBLAS_INLINE
2056 iterator1 begin1 () {
2057 return find1 (0, 0, 0);
2058 }
2059 BOOST_UBLAS_INLINE
2060 iterator1 end1 () {
2061 return find1 (0, size1 (), 0);
2062 }
2063
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> {
2070 public:
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;
2077
2078 typedef const_iterator1 dual_iterator_type;
2079 typedef const_reverse_iterator1 dual_reverse_iterator_type;
2080
2081 // Construction and destruction
2082 BOOST_UBLAS_INLINE
2083 const_iterator2 ():
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_ () {}
2088 BOOST_UBLAS_INLINE
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_)
2097 current_ = 1;
2098 if (current_ == 1 && it2_ == it2_end_)
2099 current_ = 0;
2100 if ((current_ == 0 && it1_ == it1_end_) ||
2101 (current_ == 1 && it2_ == it2_end_))
2102 current_ = end_;
2103 BOOST_UBLAS_CHECK (current_ == end_ ||
2104 (current_ == 0 && it1_ != it1_end_) ||
2105 (current_ == 1 && it2_ != it2_end_), internal_logic ());
2106 }
2107 // FIXME cannot compiler
2108 // iterator2 does not have these members!
2109 BOOST_UBLAS_INLINE
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 ());
2118 }
2119
2120 // Arithmetic
2121 BOOST_UBLAS_INLINE
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 ());
2126 ++ it1_;
2127 if (it1_ == it1_end_ && end_ == 1) {
2128 it2_ = it2_begin_;
2129 current_ = 1;
2130 }
2131 } else /* if (current_ == 1) */ {
2132 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
2133 ++ it2_;
2134 if (it2_ == it2_end_ && end_ == 0) {
2135 it1_ = it1_begin_;
2136 current_ = 0;
2137 }
2138 }
2139 return *this;
2140 }
2141 BOOST_UBLAS_INLINE
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) {
2146 it2_ = it2_end_;
2147 BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
2148 -- it2_;
2149 current_ = 1;
2150 } else {
2151 -- it1_;
2152 }
2153 } else /* if (current_ == 1) */ {
2154 if (it2_ == it2_begin_ && begin_ == 0) {
2155 it1_ = it1_end_;
2156 BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
2157 -- it1_;
2158 current_ = 0;
2159 } else {
2160 -- it2_;
2161 }
2162 }
2163 return *this;
2164 }
2165 BOOST_UBLAS_INLINE
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_);
2170 it1_ += d;
2171 n -= d;
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;
2176 n -= d;
2177 current_ = 1;
2178 }
2179 } else /* if (current_ == 1) */ {
2180 size_type d = (std::min) (n, it2_end_ - it2_);
2181 it2_ += d;
2182 n -= d;
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;
2187 n -= d;
2188 current_ = 0;
2189 }
2190 }
2191 BOOST_UBLAS_CHECK (n == 0, external_logic ());
2192 return *this;
2193 }
2194 BOOST_UBLAS_INLINE
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_);
2199 it1_ -= d;
2200 n -= d;
2201 if (n > 0) {
2202 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
2203 d = (std::min) (n, it2_end_ - it2_begin_);
2204 it2_ = it2_end_ - d;
2205 n -= d;
2206 current_ = 1;
2207 }
2208 } else /* if (current_ == 1) */ {
2209 size_type d = (std::min) (n, it2_ - it2_begin_);
2210 it2_ -= d;
2211 n -= d;
2212 if (n > 0) {
2213 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
2214 d = (std::min) (n, it1_end_ - it1_begin_);
2215 it1_ = it1_end_ - d;
2216 n -= d;
2217 current_ = 0;
2218 }
2219 }
2220 BOOST_UBLAS_CHECK (n == 0, external_logic ());
2221 return *this;
2222 }
2223 BOOST_UBLAS_INLINE
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_);
2236 }
2237
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_);
2243 }
2244 } else /* if (current_ == 1 && it.current_ == 1) */ {
2245 return it2_ - it.it2_;
2246 }
2247 }
2248
2249 // Dereference
2250 BOOST_UBLAS_INLINE
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 ()))
2256 return *it1_;
2257 else
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 ()))
2262 return *it2_;
2263 else
2264 return type_traits<value_type>::conj (*it2_);
2265 }
2266 }
2267 BOOST_UBLAS_INLINE
2268 const_reference operator [] (difference_type n) const {
2269 return *(*this + n);
2270 }
2271
2272#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2273 BOOST_UBLAS_INLINE
2274#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2275 typename self_type::
2276#endif
2277 const_iterator1 begin () const {
2278 return (*this) ().find1 (1, 0, index2 ());
2279 }
2280 BOOST_UBLAS_INLINE
2281#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2282 typename self_type::
2283#endif
2284 const_iterator1 cbegin () const {
2285 return begin ();
2286 }
2287 BOOST_UBLAS_INLINE
2288#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2289 typename self_type::
2290#endif
2291 const_iterator1 end () const {
2292 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
2293 }
2294 BOOST_UBLAS_INLINE
2295#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2296 typename self_type::
2297#endif
2298 const_iterator1 cend () const {
2299 return end ();
2300 }
2301 BOOST_UBLAS_INLINE
2302#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2303 typename self_type::
2304#endif
2305 const_reverse_iterator1 rbegin () const {
2306 return const_reverse_iterator1 (end ());
2307 }
2308 BOOST_UBLAS_INLINE
2309#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2310 typename self_type::
2311#endif
2312 const_reverse_iterator1 crbegin () const {
2313 return rbegin ();
2314 }
2315 BOOST_UBLAS_INLINE
2316#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2317 typename self_type::
2318#endif
2319 const_reverse_iterator1 rend () const {
2320 return const_reverse_iterator1 (begin ());
2321 }
2322 BOOST_UBLAS_INLINE
2323#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2324 typename self_type::
2325#endif
2326 const_reverse_iterator1 crend () const {
2327 return end ();
2328 }
2329#endif
2330
2331 // Indices
2332 BOOST_UBLAS_INLINE
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 ();
2341 }
2342 }
2343 BOOST_UBLAS_INLINE
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 ();
2352 }
2353 }
2354
2355 // Assignment
2356 BOOST_UBLAS_INLINE
2357 const_iterator2 &operator = (const const_iterator2 &it) {
2358 container_const_reference<self_type>::assign (&it ());
2359 begin_ = it.begin_;
2360 end_ = it.end_;
2361 current_ = it.current_;
2362 it1_begin_ = it.it1_begin_;
2363 it1_end_ = it.it1_end_;
2364 it1_ = it.it1_;
2365 it2_begin_ = it.it2_begin_;
2366 it2_end_ = it.it2_end_;
2367 it2_ = it.it2_;
2368 return *this;
2369 }
2370
2371 // Comparison
2372 BOOST_UBLAS_INLINE
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_);
2380 }
2381 BOOST_UBLAS_INLINE
2382 bool operator < (const const_iterator2 &it) const {
2383 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2384 return it - *this > 0;
2385 }
2386
2387 private:
2388 int begin_;
2389 int end_;
2390 int current_;
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_;
2397 };
2398#endif
2399
2400 BOOST_UBLAS_INLINE
2401 const_iterator2 begin2 () const {
2402 return find2 (0, 0, 0);
2403 }
2404 BOOST_UBLAS_INLINE
2405 const_iterator2 cbegin2 () const {
2406 return begin2 ();
2407 }
2408 BOOST_UBLAS_INLINE
2409 const_iterator2 end2 () const {
2410 return find2 (0, 0, size2 ());
2411 }
2412 BOOST_UBLAS_INLINE
2413 const_iterator2 cend2 () const {
2414 return end2 ();
2415 }
2416
2417#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2418 class iterator2:
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> {
2423 public:
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;
2428
2429 typedef iterator1 dual_iterator_type;
2430 typedef reverse_iterator1 dual_reverse_iterator_type;
2431
2432 // Construction and destruction
2433 BOOST_UBLAS_INLINE
2434 iterator2 ():
2435 container_reference<self_type> (), it2_ () {}
2436 BOOST_UBLAS_INLINE
2437 iterator2 (self_type &m, const subiterator2_type &it2):
2438 container_reference<self_type> (m), it2_ (it2) {}
2439
2440 // Arithmetic
2441 BOOST_UBLAS_INLINE
2442 iterator2 &operator ++ () {
2443 ++ it2_;
2444 return *this;
2445 }
2446 BOOST_UBLAS_INLINE
2447 iterator2 &operator -- () {
2448 -- it2_;
2449 return *this;
2450 }
2451 BOOST_UBLAS_INLINE
2452 iterator2 &operator += (difference_type n) {
2453 it2_ += n;
2454 return *this;
2455 }
2456 BOOST_UBLAS_INLINE
2457 iterator2 &operator -= (difference_type n) {
2458 it2_ -= n;
2459 return *this;
2460 }
2461 BOOST_UBLAS_INLINE
2462 difference_type operator - (const iterator2 &it) const {
2463 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2464 return it2_ - it.it2_;
2465 }
2466
2467 // Dereference
2468 BOOST_UBLAS_INLINE
2469 reference operator * () const {
2470 return *it2_;
2471 }
2472 BOOST_UBLAS_INLINE
2473 reference operator [] (difference_type n) const {
2474 return *(*this + n);
2475 }
2476
2477#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2478 BOOST_UBLAS_INLINE
2479#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2480 typename self_type::
2481#endif
2482 iterator1 begin () const {
2483 return (*this) ().find1 (1, 0, index2 ());
2484 }
2485 BOOST_UBLAS_INLINE
2486#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2487 typename self_type::
2488#endif
2489 iterator1 end () const {
2490 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
2491 }
2492 BOOST_UBLAS_INLINE
2493#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2494 typename self_type::
2495#endif
2496 reverse_iterator1 rbegin () const {
2497 return reverse_iterator1 (end ());
2498 }
2499 BOOST_UBLAS_INLINE
2500#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2501 typename self_type::
2502#endif
2503 reverse_iterator1 rend () const {
2504 return reverse_iterator1 (begin ());
2505 }
2506#endif
2507
2508 // Indices
2509 BOOST_UBLAS_INLINE
2510 size_type index1 () const {
2511 return it2_.index1 ();
2512 }
2513 BOOST_UBLAS_INLINE
2514 size_type index2 () const {
2515 return it2_.index2 ();
2516 }
2517
2518 // Assignment
2519 BOOST_UBLAS_INLINE
2520 iterator2 &operator = (const iterator2 &it) {
2521 container_reference<self_type>::assign (&it ());
2522 it2_ = it.it2_;
2523 return *this;
2524 }
2525
2526 // Comparison
2527 BOOST_UBLAS_INLINE
2528 bool operator == (const iterator2 &it) const {
2529 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2530 return it2_ == it.it2_;
2531 }
2532 BOOST_UBLAS_INLINE
2533 bool operator < (const iterator2 &it) const {
2534 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2535 return it2_ < it.it2_;
2536 }
2537
2538 private:
2539 subiterator2_type it2_;
2540
2541 friend class const_iterator2;
2542 };
2543#endif
2544
2545 BOOST_UBLAS_INLINE
2546 iterator2 begin2 () {
2547 return find2 (0, 0, 0);
2548 }
2549 BOOST_UBLAS_INLINE
2550 iterator2 end2 () {
2551 return find2 (0, 0, size2 ());
2552 }
2553
2554 // Reverse iterators
2555
2556 BOOST_UBLAS_INLINE
2557 const_reverse_iterator1 rbegin1 () const {
2558 return const_reverse_iterator1 (end1 ());
2559 }
2560 BOOST_UBLAS_INLINE
2561 const_reverse_iterator1 crbegin1 () const {
2562 return rbegin1();
2563 }
2564 BOOST_UBLAS_INLINE
2565 const_reverse_iterator1 rend1 () const {
2566 return const_reverse_iterator1 (begin1 ());
2567 }
2568 BOOST_UBLAS_INLINE
2569 const_reverse_iterator1 crend1 () const {
2570 return rend1 ();
2571 }
2572
2573 BOOST_UBLAS_INLINE
2574 reverse_iterator1 rbegin1 () {
2575 return reverse_iterator1 (end1 ());
2576 }
2577 BOOST_UBLAS_INLINE
2578 reverse_iterator1 rend1 () {
2579 return reverse_iterator1 (begin1 ());
2580 }
2581
2582 BOOST_UBLAS_INLINE
2583 const_reverse_iterator2 rbegin2 () const {
2584 return const_reverse_iterator2 (end2 ());
2585 }
2586 BOOST_UBLAS_INLINE
2587 const_reverse_iterator2 crbegin2 () const {
2588 return rbegin2 ();
2589 }
2590 BOOST_UBLAS_INLINE
2591 const_reverse_iterator2 rend2 () const {
2592 return const_reverse_iterator2 (begin2 ());
2593 }
2594 BOOST_UBLAS_INLINE
2595 const_reverse_iterator2 crend2 () const {
2596 return rend2 ();
2597 }
2598
2599 BOOST_UBLAS_INLINE
2600 reverse_iterator2 rbegin2 () {
2601 return reverse_iterator2 (end2 ());
2602 }
2603 BOOST_UBLAS_INLINE
2604 reverse_iterator2 rend2 () {
2605 return reverse_iterator2 (begin2 ());
2606 }
2607
2608 private:
2609 matrix_closure_type data_;
2610 static value_type conj_;
2611 };
2612
2613 template<class M, class TRI>
2614 typename hermitian_adaptor<M, TRI>::value_type hermitian_adaptor<M, TRI>::conj_;
2615
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 > {} ;
2623
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 > {} ;
2630
2631}}}
2632
2633#endif
2634

source code of boost/libs/numeric/ublas/include/boost/numeric/ublas/hermitian.hpp