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