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 23 namespace boost { namespace numeric { namespace ublas { 24 25 template<class M> is_hermitian(const M & 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 hermitian_matrix_element(matrix_type & m,size_type i,size_type j,value_type d)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 ~hermitian_matrix_element()59 ~hermitian_matrix_element () { 60 if (dirty_) 61 (*this) ().insert_element (i_, j_, d_); 62 } 63 64 // Assignment 65 BOOST_UBLAS_INLINE operator =(const hermitian_matrix_element & p)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 operator =(const D & d)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 operator +=(const D & d)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 operator -=(const D & d)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 operator *=(const D & d)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 operator /=(const D & d)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 operator ==(const D & d) const111 bool operator == (const D &d) const { 112 return d_ == d; 113 } 114 template<class D> 115 BOOST_UBLAS_INLINE operator !=(const D & d) const116 bool operator != (const D &d) const { 117 return d_ != d; 118 } 119 120 // Conversion 121 BOOST_UBLAS_INLINE operator const_reference() const122 operator const_reference () const { 123 return d_; 124 } 125 126 // Swapping 127 BOOST_UBLAS_INLINE swap(hermitian_matrix_element p)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 swap(hermitian_matrix_element p1,hermitian_matrix_element p2)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 realboost::numeric::ublas::type_traits162 real_type real (const_reference t) { 163 return type_traits<element_type>::real (t); 164 } 165 static 166 BOOST_UBLAS_INLINE imagboost::numeric::ublas::type_traits167 real_type imag (const_reference t) { 168 return type_traits<element_type>::imag (t); 169 } 170 static 171 BOOST_UBLAS_INLINE conjboost::numeric::ublas::type_traits172 value_type conj (const_reference t) { 173 return type_traits<element_type>::conj (t); 174 } 175 176 static 177 BOOST_UBLAS_INLINE type_absboost::numeric::ublas::type_traits178 real_type type_abs (const_reference t) { 179 return type_traits<element_type>::type_abs (t); 180 } 181 static 182 BOOST_UBLAS_INLINE type_sqrtboost::numeric::ublas::type_traits183 value_type type_sqrt (const_reference t) { 184 return type_traits<element_type>::type_sqrt (t); 185 } 186 187 static 188 BOOST_UBLAS_INLINE norm_1boost::numeric::ublas::type_traits189 real_type norm_1 (const_reference t) { 190 return type_traits<element_type>::norm_1 (t); 191 } 192 static 193 BOOST_UBLAS_INLINE norm_2boost::numeric::ublas::type_traits194 real_type norm_2 (const_reference t) { 195 return type_traits<element_type>::norm_2 (t); 196 } 197 static 198 BOOST_UBLAS_INLINE norm_infboost::numeric::ublas::type_traits199 real_type norm_inf (const_reference t) { 200 return type_traits<element_type>::norm_inf (t); 201 } 202 203 static 204 BOOST_UBLAS_INLINE equalsboost::numeric::ublas::type_traits205 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 hermitian_matrix()278 hermitian_matrix (): 279 matrix_container<self_type> (), 280 size_ (0), data_ (0) {} 281 BOOST_UBLAS_INLINE hermitian_matrix(size_type size)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 hermitian_matrix(size_type size1,size_type size2)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 hermitian_matrix(size_type size,const array_type & data)292 hermitian_matrix (size_type size, const array_type &data): 293 matrix_container<self_type> (), 294 size_ (size), data_ (data) {} 295 BOOST_UBLAS_INLINE hermitian_matrix(const hermitian_matrix & m)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 hermitian_matrix(const matrix_expression<AE> & ae)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 size1() const310 size_type size1 () const { 311 return size_; 312 } 313 BOOST_UBLAS_INLINE size2() const314 size_type size2 () const { 315 return size_; 316 } 317 318 // Storage accessors 319 BOOST_UBLAS_INLINE data() const320 const array_type &data () const { 321 return data_; 322 } 323 BOOST_UBLAS_INLINE data()324 array_type &data () { 325 return data_; 326 } 327 328 // Resizing 329 BOOST_UBLAS_INLINE resize(size_type size,bool preserve=true)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 resize(size_type size1,size_type size2,bool preserve=true)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 resize_packed_preserve(size_type size)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 operator ()(size_type i,size_type j) const352 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 at_element(size_type i,size_type j)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 operator ()(size_type i,size_type j)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 insert_element(size_type i,size_type j,const_reference t)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 erase_element(size_type i,size_type j)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 clear()406 void clear () { 407 std::fill (data ().begin (), data ().end (), value_type/*zero*/()); 408 } 409 410 // Assignment 411 BOOST_UBLAS_INLINE operator =(const hermitian_matrix & m)412 hermitian_matrix &operator = (const hermitian_matrix &m) { 413 size_ = m.size_; 414 data () = m.data (); 415 return *this; 416 } 417 BOOST_UBLAS_INLINE assign_temporary(hermitian_matrix & m)418 hermitian_matrix &assign_temporary (hermitian_matrix &m) { 419 swap (m); 420 return *this; 421 } 422 template<class AE> 423 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)424 hermitian_matrix &operator = (const matrix_expression<AE> &ae) { 425 self_type temporary (ae); 426 return assign_temporary (temporary); 427 } 428 template<class AE> 429 BOOST_UBLAS_INLINE assign(const matrix_expression<AE> & ae)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 operator +=(const matrix_expression<AE> & ae)436 hermitian_matrix& operator += (const matrix_expression<AE> &ae) { 437 self_type temporary (*this + ae); 438 return assign_temporary (temporary); 439 } 440 template<class AE> 441 BOOST_UBLAS_INLINE plus_assign(const matrix_expression<AE> & ae)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 operator -=(const matrix_expression<AE> & ae)448 hermitian_matrix& operator -= (const matrix_expression<AE> &ae) { 449 self_type temporary (*this - ae); 450 return assign_temporary (temporary); 451 } 452 template<class AE> 453 BOOST_UBLAS_INLINE minus_assign(const matrix_expression<AE> & ae)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 operator *=(const AT & at)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 operator /=(const AT & at)470 hermitian_matrix& operator /= (const AT &at) { 471 // Multiplication is only allowed for real scalars, 472 // otherwise the resulting matrix isn't hermitian. 473 // Thanks to Peter Schmitteckert for spotting this. 474 BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ()); 475 matrix_assign_scalar<scalar_divides_assign> (*this, at); 476 return *this; 477 } 478 479 // Swapping 480 BOOST_UBLAS_INLINE swap(hermitian_matrix & m)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 swap(hermitian_matrix & m1,hermitian_matrix & m2)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 find1(int,size_type i,size_type j) const511 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const { 512 return const_iterator1 (*this, i, j); 513 } 514 BOOST_UBLAS_INLINE find1(int rank,size_type i,size_type j)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 find2(int,size_type i,size_type j) const523 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const { 524 return const_iterator2 (*this, i, j); 525 } 526 BOOST_UBLAS_INLINE find2(int rank,size_type i,size_type j)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 const_iterator1()553 const_iterator1 (): 554 container_const_reference<self_type> (), it1_ (), it2_ () {} 555 BOOST_UBLAS_INLINE const_iterator1(const self_type & m,size_type it1,size_type it2)556 const_iterator1 (const self_type &m, size_type it1, size_type it2): 557 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {} 558 BOOST_UBLAS_INLINE const_iterator1(const iterator1 & it)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 operator ++()564 const_iterator1 &operator ++ () { 565 ++ it1_; 566 return *this; 567 } 568 BOOST_UBLAS_INLINE operator --()569 const_iterator1 &operator -- () { 570 -- it1_; 571 return *this; 572 } 573 BOOST_UBLAS_INLINE operator +=(difference_type n)574 const_iterator1 &operator += (difference_type n) { 575 it1_ += n; 576 return *this; 577 } 578 BOOST_UBLAS_INLINE operator -=(difference_type n)579 const_iterator1 &operator -= (difference_type n) { 580 it1_ -= n; 581 return *this; 582 } 583 BOOST_UBLAS_INLINE operator -(const const_iterator1 & it) const584 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 operator *() const592 const_reference operator * () const { 593 return (*this) () (it1_, it2_); 594 } 595 BOOST_UBLAS_INLINE operator [](difference_type n) const596 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 begin() const605 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 cbegin() const612 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 end() const619 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 cend() const626 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 rbegin() const633 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 crbegin() const640 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 rend() const647 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 crend() const654 const_reverse_iterator2 crend () const { 655 return rend (); 656 } 657 #endif 658 659 // Indices 660 BOOST_UBLAS_INLINE index1() const661 size_type index1 () const { 662 return it1_; 663 } 664 BOOST_UBLAS_INLINE index2() const665 size_type index2 () const { 666 return it2_; 667 } 668 669 // Assignment 670 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)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 operator ==(const const_iterator1 & it) const680 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 operator <(const const_iterator1 & it) const686 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 begin1() const699 const_iterator1 begin1 () const { 700 return find1 (0, 0, 0); 701 } 702 BOOST_UBLAS_INLINE cbegin1() const703 const_iterator1 cbegin1 () const { 704 return begin1 (); 705 } 706 BOOST_UBLAS_INLINE end1() const707 const_iterator1 end1 () const { 708 return find1 (0, size_, 0); 709 } 710 BOOST_UBLAS_INLINE cend1() const711 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 iterator1()731 iterator1 (): 732 container_reference<self_type> (), it1_ (), it2_ () {} 733 BOOST_UBLAS_INLINE iterator1(self_type & m,size_type it1,size_type it2)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 operator ++()739 iterator1 &operator ++ () { 740 ++ it1_; 741 return *this; 742 } 743 BOOST_UBLAS_INLINE operator --()744 iterator1 &operator -- () { 745 -- it1_; 746 return *this; 747 } 748 BOOST_UBLAS_INLINE operator +=(difference_type n)749 iterator1 &operator += (difference_type n) { 750 it1_ += n; 751 return *this; 752 } 753 BOOST_UBLAS_INLINE operator -=(difference_type n)754 iterator1 &operator -= (difference_type n) { 755 it1_ -= n; 756 return *this; 757 } 758 BOOST_UBLAS_INLINE operator -(const iterator1 & it) const759 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 operator *() const767 reference operator * () const { 768 return (*this) ().at_element (it1_, it2_); 769 } 770 BOOST_UBLAS_INLINE operator [](difference_type n) const771 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 begin() const780 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 end() const787 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 rbegin() const794 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 rend() const801 reverse_iterator2 rend () const { 802 return reverse_iterator2 (begin ()); 803 } 804 #endif 805 806 // Indices 807 BOOST_UBLAS_INLINE index1() const808 size_type index1 () const { 809 return it1_; 810 } 811 BOOST_UBLAS_INLINE index2() const812 size_type index2 () const { 813 return it2_; 814 } 815 816 // Assignment 817 BOOST_UBLAS_INLINE operator =(const iterator1 & it)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 operator ==(const iterator1 & it) const827 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 operator <(const iterator1 & it) const833 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 begin1()848 iterator1 begin1 () { 849 return find1 (0, 0, 0); 850 } 851 BOOST_UBLAS_INLINE end1()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 const_iterator2()872 const_iterator2 (): 873 container_const_reference<self_type> (), it1_ (), it2_ () {} 874 BOOST_UBLAS_INLINE const_iterator2(const self_type & m,size_type it1,size_type it2)875 const_iterator2 (const self_type &m, size_type it1, size_type it2): 876 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {} 877 BOOST_UBLAS_INLINE const_iterator2(const iterator2 & it)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 operator ++()883 const_iterator2 &operator ++ () { 884 ++ it2_; 885 return *this; 886 } 887 BOOST_UBLAS_INLINE operator --()888 const_iterator2 &operator -- () { 889 -- it2_; 890 return *this; 891 } 892 BOOST_UBLAS_INLINE operator +=(difference_type n)893 const_iterator2 &operator += (difference_type n) { 894 it2_ += n; 895 return *this; 896 } 897 BOOST_UBLAS_INLINE operator -=(difference_type n)898 const_iterator2 &operator -= (difference_type n) { 899 it2_ -= n; 900 return *this; 901 } 902 BOOST_UBLAS_INLINE operator -(const const_iterator2 & it) const903 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 operator *() const911 const_reference operator * () const { 912 return (*this) () (it1_, it2_); 913 } 914 BOOST_UBLAS_INLINE operator [](difference_type n) const915 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 begin() const924 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 cbegin() const931 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 end() const938 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 cend() const945 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 rbegin() const952 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 crbegin() const959 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 rend() const966 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 crend() const973 const_iterator1 crend () const { 974 return rend (); 975 } 976 #endif 977 978 // Indices 979 BOOST_UBLAS_INLINE index1() const980 size_type index1 () const { 981 return it1_; 982 } 983 BOOST_UBLAS_INLINE index2() const984 size_type index2 () const { 985 return it2_; 986 } 987 988 // Assignment 989 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)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 operator ==(const const_iterator2 & it) const999 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 operator <(const const_iterator2 & it) const1005 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 begin2() const1018 const_iterator2 begin2 () const { 1019 return find2 (0, 0, 0); 1020 } 1021 BOOST_UBLAS_INLINE cbegin2() const1022 const_iterator2 cbegin2 () const { 1023 return begin2 (); 1024 } 1025 BOOST_UBLAS_INLINE end2() const1026 const_iterator2 end2 () const { 1027 return find2 (0, 0, size_); 1028 } 1029 BOOST_UBLAS_INLINE cend2() const1030 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 iterator2()1050 iterator2 (): 1051 container_reference<self_type> (), it1_ (), it2_ () {} 1052 BOOST_UBLAS_INLINE iterator2(self_type & m,size_type it1,size_type it2)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 operator ++()1058 iterator2 &operator ++ () { 1059 ++ it2_; 1060 return *this; 1061 } 1062 BOOST_UBLAS_INLINE operator --()1063 iterator2 &operator -- () { 1064 -- it2_; 1065 return *this; 1066 } 1067 BOOST_UBLAS_INLINE operator +=(difference_type n)1068 iterator2 &operator += (difference_type n) { 1069 it2_ += n; 1070 return *this; 1071 } 1072 BOOST_UBLAS_INLINE operator -=(difference_type n)1073 iterator2 &operator -= (difference_type n) { 1074 it2_ -= n; 1075 return *this; 1076 } 1077 BOOST_UBLAS_INLINE operator -(const iterator2 & it) const1078 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 operator *() const1086 reference operator * () const { 1087 return (*this) ().at_element (it1_, it2_); 1088 } 1089 BOOST_UBLAS_INLINE operator [](difference_type n) const1090 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 begin() const1099 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 end() const1106 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 rbegin() const1113 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 rend() const1120 reverse_iterator1 rend () const { 1121 return reverse_iterator1 (begin ()); 1122 } 1123 #endif 1124 1125 // Indices 1126 BOOST_UBLAS_INLINE index1() const1127 size_type index1 () const { 1128 return it1_; 1129 } 1130 BOOST_UBLAS_INLINE index2() const1131 size_type index2 () const { 1132 return it2_; 1133 } 1134 1135 // Assignment 1136 BOOST_UBLAS_INLINE operator =(const iterator2 & it)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 operator ==(const iterator2 & it) const1146 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 operator <(const iterator2 & it) const1152 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 begin2()1167 iterator2 begin2 () { 1168 return find2 (0, 0, 0); 1169 } 1170 BOOST_UBLAS_INLINE end2()1171 iterator2 end2 () { 1172 return find2 (0, 0, size_); 1173 } 1174 1175 // Reverse iterators 1176 1177 BOOST_UBLAS_INLINE rbegin1() const1178 const_reverse_iterator1 rbegin1 () const { 1179 return const_reverse_iterator1 (end1 ()); 1180 } 1181 BOOST_UBLAS_INLINE crbegin1() const1182 const_reverse_iterator1 crbegin1 () const { 1183 return rbegin1 (); 1184 } 1185 BOOST_UBLAS_INLINE rend1() const1186 const_reverse_iterator1 rend1 () const { 1187 return const_reverse_iterator1 (begin1 ()); 1188 } 1189 BOOST_UBLAS_INLINE crend1() const1190 const_reverse_iterator1 crend1 () const { 1191 return rend1 (); 1192 } 1193 1194 BOOST_UBLAS_INLINE rbegin1()1195 reverse_iterator1 rbegin1 () { 1196 return reverse_iterator1 (end1 ()); 1197 } 1198 BOOST_UBLAS_INLINE rend1()1199 reverse_iterator1 rend1 () { 1200 return reverse_iterator1 (begin1 ()); 1201 } 1202 1203 BOOST_UBLAS_INLINE rbegin2() const1204 const_reverse_iterator2 rbegin2 () const { 1205 return const_reverse_iterator2 (end2 ()); 1206 } 1207 BOOST_UBLAS_INLINE crbegin2() const1208 const_reverse_iterator2 crbegin2 () const { 1209 return rbegin2(); 1210 } 1211 BOOST_UBLAS_INLINE rend2() const1212 const_reverse_iterator2 rend2 () const { 1213 return const_reverse_iterator2 (begin2 ()); 1214 } 1215 BOOST_UBLAS_INLINE crend2() const1216 const_reverse_iterator2 crend2 () const { 1217 return rend2 (); 1218 } 1219 1220 BOOST_UBLAS_INLINE rbegin2()1221 reverse_iterator2 rbegin2 () { 1222 return reverse_iterator2 (end2 ()); 1223 } 1224 BOOST_UBLAS_INLINE rend2()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 hermitian_adaptor(matrix_type & data)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 hermitian_adaptor(const hermitian_adaptor & m)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 size1() const1297 size_type size1 () const { 1298 return data_.size1 (); 1299 } 1300 BOOST_UBLAS_INLINE size2() const1301 size_type size2 () const { 1302 return data_.size2 (); 1303 } 1304 1305 // Storage accessors 1306 BOOST_UBLAS_INLINE data() const1307 const matrix_closure_type &data () const { 1308 return data_; 1309 } 1310 BOOST_UBLAS_INLINE data()1311 matrix_closure_type &data () { 1312 return data_; 1313 } 1314 1315 // Element access 1316 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 1317 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const1318 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 operator ()(size_type i,size_type j)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 insert_element(size_type i,size_type j,value_type t)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 operator ()(size_type i,size_type j)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 insert_element(size_type i,size_type j,value_type t)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 operator =(const hermitian_adaptor & m)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 assign_temporary(hermitian_adaptor & m)1399 hermitian_adaptor &assign_temporary (hermitian_adaptor &m) { 1400 *this = m; 1401 return *this; 1402 } 1403 template<class AE> 1404 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)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 assign(const matrix_expression<AE> & ae)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 operator +=(const matrix_expression<AE> & ae)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 plus_assign(const matrix_expression<AE> & ae)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 operator -=(const matrix_expression<AE> & ae)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 minus_assign(const matrix_expression<AE> & ae)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 operator *=(const AT & at)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 operator /=(const AT & at)1451 hermitian_adaptor& operator /= (const AT &at) { 1452 // Multiplication is only allowed for real scalars, 1453 // otherwise the resulting matrix isn't hermitian. 1454 // Thanks to Peter Schmitteckert for spotting this. 1455 BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ()); 1456 matrix_assign_scalar<scalar_divides_assign> (*this, at); 1457 return *this; 1458 } 1459 1460 // Closure comparison 1461 BOOST_UBLAS_INLINE same_closure(const hermitian_adaptor & ha) const1462 bool same_closure (const hermitian_adaptor &ha) const { 1463 return (*this).data ().same_closure (ha.data ()); 1464 } 1465 1466 // Swapping 1467 BOOST_UBLAS_INLINE swap(hermitian_adaptor & m)1468 void swap (hermitian_adaptor &m) { 1469 if (this != &m) 1470 matrix_swap<scalar_swap, triangular_type> (*this, m); 1471 } 1472 BOOST_UBLAS_INLINE swap(hermitian_adaptor & m1,hermitian_adaptor & m2)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 find1(int rank,size_type i,size_type j) const1508 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 find1(int rank,size_type i,size_type j)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 find2(int rank,size_type i,size_type j) const1540 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 find2(int rank,size_type i,size_type j)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 const_iterator1()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 const_iterator1(const self_type & m,int begin,int end,const const_subiterator1_type & it1_begin,const const_subiterator1_type & it1_end,const const_subiterator2_type & it2_begin,const const_subiterator2_type & it2_end)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 const_iterator1(const iterator1 & it)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 operator ++()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 operator --()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 operator +=(difference_type n)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 operator -=(difference_type n)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 operator -(const const_iterator1 & it) const1734 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 operator *() const1761 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 operator [](difference_type n) const1778 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 begin() const1787 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 cbegin() const1794 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 end() const1801 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 cend() const1808 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 rbegin() const1815 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 crbegin() const1822 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 rend() const1829 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 crend() const1836 const_reverse_iterator2 crend () const { 1837 return rend (); 1838 } 1839 #endif 1840 1841 // Indices 1842 BOOST_UBLAS_INLINE index1() const1843 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 index2() const1854 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 operator =(const const_iterator1 & it)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 operator ==(const const_iterator1 & it) const1883 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 operator <(const const_iterator1 & it) const1892 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 begin1() const1911 const_iterator1 begin1 () const { 1912 return find1 (0, 0, 0); 1913 } 1914 BOOST_UBLAS_INLINE cbegin1() const1915 const_iterator1 cbegin1 () const { 1916 return begin1 (); 1917 } 1918 BOOST_UBLAS_INLINE end1() const1919 const_iterator1 end1 () const { 1920 return find1 (0, size1 (), 0); 1921 } 1922 BOOST_UBLAS_INLINE cend1() const1923 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 iterator1()1944 iterator1 (): 1945 container_reference<self_type> (), it1_ () {} 1946 BOOST_UBLAS_INLINE iterator1(self_type & m,const subiterator1_type & it1)1947 iterator1 (self_type &m, const subiterator1_type &it1): 1948 container_reference<self_type> (m), it1_ (it1) {} 1949 1950 // Arithmetic 1951 BOOST_UBLAS_INLINE operator ++()1952 iterator1 &operator ++ () { 1953 ++ it1_; 1954 return *this; 1955 } 1956 BOOST_UBLAS_INLINE operator --()1957 iterator1 &operator -- () { 1958 -- it1_; 1959 return *this; 1960 } 1961 BOOST_UBLAS_INLINE operator +=(difference_type n)1962 iterator1 &operator += (difference_type n) { 1963 it1_ += n; 1964 return *this; 1965 } 1966 BOOST_UBLAS_INLINE operator -=(difference_type n)1967 iterator1 &operator -= (difference_type n) { 1968 it1_ -= n; 1969 return *this; 1970 } 1971 BOOST_UBLAS_INLINE operator -(const iterator1 & it) const1972 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 operator *() const1979 reference operator * () const { 1980 return *it1_; 1981 } 1982 BOOST_UBLAS_INLINE operator [](difference_type n) const1983 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 begin() const1992 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 end() const1999 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 rbegin() const2006 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 rend() const2013 reverse_iterator2 rend () const { 2014 return reverse_iterator2 (begin ()); 2015 } 2016 #endif 2017 2018 // Indices 2019 BOOST_UBLAS_INLINE index1() const2020 size_type index1 () const { 2021 return it1_.index1 (); 2022 } 2023 BOOST_UBLAS_INLINE index2() const2024 size_type index2 () const { 2025 return it1_.index2 (); 2026 } 2027 2028 // Assignment 2029 BOOST_UBLAS_INLINE operator =(const iterator1 & it)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 operator ==(const iterator1 & it) const2038 bool operator == (const iterator1 &it) const { 2039 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2040 return it1_ == it.it1_; 2041 } 2042 BOOST_UBLAS_INLINE operator <(const iterator1 & it) const2043 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 begin1()2056 iterator1 begin1 () { 2057 return find1 (0, 0, 0); 2058 } 2059 BOOST_UBLAS_INLINE end1()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 const_iterator2()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 const_iterator2(const self_type & m,int begin,int end,const const_subiterator1_type & it1_begin,const const_subiterator1_type & it1_end,const const_subiterator2_type & it2_begin,const const_subiterator2_type & it2_end)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 const_iterator2(const iterator2 & it)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 operator ++()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 operator --()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 operator +=(difference_type n)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 operator -=(difference_type n)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 operator -(const const_iterator2 & it) const2224 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 operator *() const2251 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 operator [](difference_type n) const2268 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 begin() const2277 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 cbegin() const2284 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 end() const2291 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 cend() const2298 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 rbegin() const2305 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 crbegin() const2312 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 rend() const2319 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 crend() const2326 const_reverse_iterator1 crend () const { 2327 return end (); 2328 } 2329 #endif 2330 2331 // Indices 2332 BOOST_UBLAS_INLINE index1() const2333 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 index2() const2344 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 operator =(const const_iterator2 & it)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 operator ==(const const_iterator2 & it) const2373 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 operator <(const const_iterator2 & it) const2382 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 begin2() const2401 const_iterator2 begin2 () const { 2402 return find2 (0, 0, 0); 2403 } 2404 BOOST_UBLAS_INLINE cbegin2() const2405 const_iterator2 cbegin2 () const { 2406 return begin2 (); 2407 } 2408 BOOST_UBLAS_INLINE end2() const2409 const_iterator2 end2 () const { 2410 return find2 (0, 0, size2 ()); 2411 } 2412 BOOST_UBLAS_INLINE cend2() const2413 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 iterator2()2434 iterator2 (): 2435 container_reference<self_type> (), it2_ () {} 2436 BOOST_UBLAS_INLINE iterator2(self_type & m,const subiterator2_type & it2)2437 iterator2 (self_type &m, const subiterator2_type &it2): 2438 container_reference<self_type> (m), it2_ (it2) {} 2439 2440 // Arithmetic 2441 BOOST_UBLAS_INLINE operator ++()2442 iterator2 &operator ++ () { 2443 ++ it2_; 2444 return *this; 2445 } 2446 BOOST_UBLAS_INLINE operator --()2447 iterator2 &operator -- () { 2448 -- it2_; 2449 return *this; 2450 } 2451 BOOST_UBLAS_INLINE operator +=(difference_type n)2452 iterator2 &operator += (difference_type n) { 2453 it2_ += n; 2454 return *this; 2455 } 2456 BOOST_UBLAS_INLINE operator -=(difference_type n)2457 iterator2 &operator -= (difference_type n) { 2458 it2_ -= n; 2459 return *this; 2460 } 2461 BOOST_UBLAS_INLINE operator -(const iterator2 & it) const2462 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 operator *() const2469 reference operator * () const { 2470 return *it2_; 2471 } 2472 BOOST_UBLAS_INLINE operator [](difference_type n) const2473 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 begin() const2482 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 end() const2489 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 rbegin() const2496 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 rend() const2503 reverse_iterator1 rend () const { 2504 return reverse_iterator1 (begin ()); 2505 } 2506 #endif 2507 2508 // Indices 2509 BOOST_UBLAS_INLINE index1() const2510 size_type index1 () const { 2511 return it2_.index1 (); 2512 } 2513 BOOST_UBLAS_INLINE index2() const2514 size_type index2 () const { 2515 return it2_.index2 (); 2516 } 2517 2518 // Assignment 2519 BOOST_UBLAS_INLINE operator =(const iterator2 & it)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 operator ==(const iterator2 & it) const2528 bool operator == (const iterator2 &it) const { 2529 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2530 return it2_ == it.it2_; 2531 } 2532 BOOST_UBLAS_INLINE operator <(const iterator2 & it) const2533 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 begin2()2546 iterator2 begin2 () { 2547 return find2 (0, 0, 0); 2548 } 2549 BOOST_UBLAS_INLINE end2()2550 iterator2 end2 () { 2551 return find2 (0, 0, size2 ()); 2552 } 2553 2554 // Reverse iterators 2555 2556 BOOST_UBLAS_INLINE rbegin1() const2557 const_reverse_iterator1 rbegin1 () const { 2558 return const_reverse_iterator1 (end1 ()); 2559 } 2560 BOOST_UBLAS_INLINE crbegin1() const2561 const_reverse_iterator1 crbegin1 () const { 2562 return rbegin1(); 2563 } 2564 BOOST_UBLAS_INLINE rend1() const2565 const_reverse_iterator1 rend1 () const { 2566 return const_reverse_iterator1 (begin1 ()); 2567 } 2568 BOOST_UBLAS_INLINE crend1() const2569 const_reverse_iterator1 crend1 () const { 2570 return rend1 (); 2571 } 2572 2573 BOOST_UBLAS_INLINE rbegin1()2574 reverse_iterator1 rbegin1 () { 2575 return reverse_iterator1 (end1 ()); 2576 } 2577 BOOST_UBLAS_INLINE rend1()2578 reverse_iterator1 rend1 () { 2579 return reverse_iterator1 (begin1 ()); 2580 } 2581 2582 BOOST_UBLAS_INLINE rbegin2() const2583 const_reverse_iterator2 rbegin2 () const { 2584 return const_reverse_iterator2 (end2 ()); 2585 } 2586 BOOST_UBLAS_INLINE crbegin2() const2587 const_reverse_iterator2 crbegin2 () const { 2588 return rbegin2 (); 2589 } 2590 BOOST_UBLAS_INLINE rend2() const2591 const_reverse_iterator2 rend2 () const { 2592 return const_reverse_iterator2 (begin2 ()); 2593 } 2594 BOOST_UBLAS_INLINE crend2() const2595 const_reverse_iterator2 crend2 () const { 2596 return rend2 (); 2597 } 2598 2599 BOOST_UBLAS_INLINE rbegin2()2600 reverse_iterator2 rbegin2 () { 2601 return reverse_iterator2 (end2 ()); 2602 } 2603 BOOST_UBLAS_INLINE rend2()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