hermitian.hpp 95 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457
  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. #ifndef BOOST_UBLAS_HERMITIAN_H
  13. #define BOOST_UBLAS_HERMITIAN_H
  14. #include <boost/numeric/ublas/matrix.hpp>
  15. #include <boost/numeric/ublas/triangular.hpp> // for resize_preserve
  16. #include <boost/numeric/ublas/detail/temporary.hpp>
  17. // Iterators based on ideas of Jeremy Siek
  18. // Hermitian matrices are square. Thanks to Peter Schmitteckert for spotting this.
  19. namespace boost { namespace numeric { namespace ublas {
  20. template<class M>
  21. bool is_hermitian (const M &m) {
  22. typedef typename M::size_type size_type;
  23. if (m.size1 () != m.size2 ())
  24. return false;
  25. size_type size = BOOST_UBLAS_SAME (m.size1 (), m.size2 ());
  26. for (size_type i = 0; i < size; ++ i) {
  27. for (size_type j = i; j < size; ++ j) {
  28. if (m (i, j) != conj (m (j, i)))
  29. return false;
  30. }
  31. }
  32. return true;
  33. }
  34. #ifdef BOOST_UBLAS_STRICT_HERMITIAN
  35. template<class M>
  36. class hermitian_matrix_element:
  37. public container_reference<M> {
  38. public:
  39. typedef M matrix_type;
  40. typedef typename M::size_type size_type;
  41. typedef typename M::value_type value_type;
  42. typedef const value_type &const_reference;
  43. typedef value_type &reference;
  44. typedef value_type *pointer;
  45. // Construction and destruction
  46. BOOST_UBLAS_INLINE
  47. hermitian_matrix_element (matrix_type &m, size_type i, size_type j, value_type d):
  48. container_reference<matrix_type> (m), i_ (i), j_ (j), d_ (d), dirty_ (false) {}
  49. BOOST_UBLAS_INLINE
  50. ~hermitian_matrix_element () {
  51. if (dirty_)
  52. (*this) ().insert_element (i_, j_, d_);
  53. }
  54. // Assignment
  55. BOOST_UBLAS_INLINE
  56. hermitian_matrix_element &operator = (const hermitian_matrix_element &p) {
  57. // Overide the implict copy assignment
  58. d_ = p.d_;
  59. dirty_ = true;
  60. return *this;
  61. }
  62. template<class D>
  63. BOOST_UBLAS_INLINE
  64. hermitian_matrix_element &operator = (const D &d) {
  65. d_ = d;
  66. dirty_ = true;
  67. return *this;
  68. }
  69. template<class D>
  70. BOOST_UBLAS_INLINE
  71. hermitian_matrix_element &operator += (const D &d) {
  72. d_ += d;
  73. dirty_ = true;
  74. return *this;
  75. }
  76. template<class D>
  77. BOOST_UBLAS_INLINE
  78. hermitian_matrix_element &operator -= (const D &d) {
  79. d_ -= d;
  80. dirty_ = true;
  81. return *this;
  82. }
  83. template<class D>
  84. BOOST_UBLAS_INLINE
  85. hermitian_matrix_element &operator *= (const D &d) {
  86. d_ *= d;
  87. dirty_ = true;
  88. return *this;
  89. }
  90. template<class D>
  91. BOOST_UBLAS_INLINE
  92. hermitian_matrix_element &operator /= (const D &d) {
  93. d_ /= d;
  94. dirty_ = true;
  95. return *this;
  96. }
  97. // Comparison
  98. template<class D>
  99. BOOST_UBLAS_INLINE
  100. bool operator == (const D &d) const {
  101. return d_ == d;
  102. }
  103. template<class D>
  104. BOOST_UBLAS_INLINE
  105. bool operator != (const D &d) const {
  106. return d_ != d;
  107. }
  108. // Conversion
  109. BOOST_UBLAS_INLINE
  110. operator const_reference () const {
  111. return d_;
  112. }
  113. // Swapping
  114. BOOST_UBLAS_INLINE
  115. void swap (hermitian_matrix_element p) {
  116. if (this != &p) {
  117. dirty_ = true;
  118. p.dirty_ = true;
  119. std::swap (d_, p.d_);
  120. }
  121. }
  122. BOOST_UBLAS_INLINE
  123. friend void swap (hermitian_matrix_element p1, hermitian_matrix_element p2) {
  124. p1.swap (p2);
  125. }
  126. private:
  127. size_type i_;
  128. size_type j_;
  129. value_type d_;
  130. bool dirty_;
  131. };
  132. template<class M>
  133. struct type_traits<hermitian_matrix_element<M> > {
  134. typedef typename M::value_type element_type;
  135. typedef type_traits<hermitian_matrix_element<M> > self_type;
  136. typedef typename type_traits<element_type>::value_type value_type;
  137. typedef typename type_traits<element_type>::const_reference const_reference;
  138. typedef hermitian_matrix_element<M> reference;
  139. typedef typename type_traits<element_type>::real_type real_type;
  140. typedef typename type_traits<element_type>::precision_type precision_type;
  141. static const unsigned plus_complexity = type_traits<element_type>::plus_complexity;
  142. static const unsigned multiplies_complexity = type_traits<element_type>::multiplies_complexity;
  143. static
  144. BOOST_UBLAS_INLINE
  145. real_type real (const_reference t) {
  146. return type_traits<element_type>::real (t);
  147. }
  148. static
  149. BOOST_UBLAS_INLINE
  150. real_type imag (const_reference t) {
  151. return type_traits<element_type>::imag (t);
  152. }
  153. static
  154. BOOST_UBLAS_INLINE
  155. value_type conj (const_reference t) {
  156. return type_traits<element_type>::conj (t);
  157. }
  158. static
  159. BOOST_UBLAS_INLINE
  160. real_type type_abs (const_reference t) {
  161. return type_traits<element_type>::type_abs (t);
  162. }
  163. static
  164. BOOST_UBLAS_INLINE
  165. value_type type_sqrt (const_reference t) {
  166. return type_traits<element_type>::type_sqrt (t);
  167. }
  168. static
  169. BOOST_UBLAS_INLINE
  170. real_type norm_1 (const_reference t) {
  171. return type_traits<element_type>::norm_1 (t);
  172. }
  173. static
  174. BOOST_UBLAS_INLINE
  175. real_type norm_2 (const_reference t) {
  176. return type_traits<element_type>::norm_2 (t);
  177. }
  178. static
  179. BOOST_UBLAS_INLINE
  180. real_type norm_inf (const_reference t) {
  181. return type_traits<element_type>::norm_inf (t);
  182. }
  183. static
  184. BOOST_UBLAS_INLINE
  185. bool equals (const_reference t1, const_reference t2) {
  186. return type_traits<element_type>::equals (t1, t2);
  187. }
  188. };
  189. template<class M1, class T2>
  190. struct promote_traits<hermitian_matrix_element<M1>, T2> {
  191. typedef typename promote_traits<typename hermitian_matrix_element<M1>::value_type, T2>::promote_type promote_type;
  192. };
  193. template<class T1, class M2>
  194. struct promote_traits<T1, hermitian_matrix_element<M2> > {
  195. typedef typename promote_traits<T1, typename hermitian_matrix_element<M2>::value_type>::promote_type promote_type;
  196. };
  197. template<class M1, class M2>
  198. struct promote_traits<hermitian_matrix_element<M1>, hermitian_matrix_element<M2> > {
  199. typedef typename promote_traits<typename hermitian_matrix_element<M1>::value_type,
  200. typename hermitian_matrix_element<M2>::value_type>::promote_type promote_type;
  201. };
  202. #endif
  203. /** \brief A hermitian matrix of values of type \c T
  204. *
  205. * For a \f$(n \times n)\f$-dimensional matrix and \f$ 0 \leq i < n, 0 \leq j < n\f$, every element
  206. * \f$m_{i,j}\f$ is mapped to the \f$(i.n + j)\f$-th element of the container for row major orientation
  207. * or the \f$(i + j.m)\f$-th element of the container for column major orientation. And
  208. * \f$\forall i,j\f$, \f$m_{i,j} = \overline{m_{i,j}}\f$.
  209. *
  210. * Orientation and storage can also be specified, otherwise a row major and unbounded array are used.
  211. * It is \b not required by the storage to initialize elements of the matrix.
  212. * Moreover, only the given triangular matrix is stored and the storage of hermitian matrices is packed.
  213. *
  214. * See http://en.wikipedia.org/wiki/Hermitian_matrix for more details on hermitian matrices.
  215. *
  216. * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
  217. * \tparam TRI the type of triangular matrix is either \c lower or \c upper. Default is \c lower
  218. * \tparam L the storage organization. It is either \c row_major or \c column_major. Default is \c row_major
  219. * \tparam A the type of Storage array. Default is \unbounded_array.
  220. */
  221. template<class T, class TRI, class L, class A>
  222. class hermitian_matrix:
  223. public matrix_container<hermitian_matrix<T, TRI, L, A> > {
  224. typedef T &true_reference;
  225. typedef T *pointer;
  226. typedef TRI triangular_type;
  227. typedef L layout_type;
  228. typedef hermitian_matrix<T, TRI, L, A> self_type;
  229. public:
  230. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  231. using matrix_container<self_type>::operator ();
  232. #endif
  233. typedef typename A::size_type size_type;
  234. typedef typename A::difference_type difference_type;
  235. typedef T value_type;
  236. // FIXME no better way to not return the address of a temporary?
  237. // typedef const T &const_reference;
  238. typedef const T const_reference;
  239. #ifndef BOOST_UBLAS_STRICT_HERMITIAN
  240. typedef T &reference;
  241. #else
  242. typedef hermitian_matrix_element<self_type> reference;
  243. #endif
  244. typedef A array_type;
  245. typedef const matrix_reference<const self_type> const_closure_type;
  246. typedef matrix_reference<self_type> closure_type;
  247. typedef vector<T, A> vector_temporary_type;
  248. typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix
  249. typedef packed_tag storage_category;
  250. typedef typename L::orientation_category orientation_category;
  251. // Construction and destruction
  252. BOOST_UBLAS_INLINE
  253. hermitian_matrix ():
  254. matrix_container<self_type> (),
  255. size_ (0), data_ (0) {}
  256. BOOST_UBLAS_INLINE
  257. hermitian_matrix (size_type size):
  258. matrix_container<self_type> (),
  259. size_ (BOOST_UBLAS_SAME (size, size)), data_ (triangular_type::packed_size (layout_type (), size, size)) {
  260. }
  261. BOOST_UBLAS_INLINE
  262. hermitian_matrix (size_type size1, size_type size2):
  263. matrix_container<self_type> (),
  264. size_ (BOOST_UBLAS_SAME (size1, size2)), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
  265. }
  266. BOOST_UBLAS_INLINE
  267. hermitian_matrix (size_type size, const array_type &data):
  268. matrix_container<self_type> (),
  269. size_ (size), data_ (data) {}
  270. BOOST_UBLAS_INLINE
  271. hermitian_matrix (const hermitian_matrix &m):
  272. matrix_container<self_type> (),
  273. size_ (m.size_), data_ (m.data_) {}
  274. template<class AE>
  275. BOOST_UBLAS_INLINE
  276. hermitian_matrix (const matrix_expression<AE> &ae):
  277. matrix_container<self_type> (),
  278. size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())),
  279. data_ (triangular_type::packed_size (layout_type (), size_, size_)) {
  280. matrix_assign<scalar_assign> (*this, ae);
  281. }
  282. // Accessors
  283. BOOST_UBLAS_INLINE
  284. size_type size1 () const {
  285. return size_;
  286. }
  287. BOOST_UBLAS_INLINE
  288. size_type size2 () const {
  289. return size_;
  290. }
  291. // Storage accessors
  292. BOOST_UBLAS_INLINE
  293. const array_type &data () const {
  294. return data_;
  295. }
  296. BOOST_UBLAS_INLINE
  297. array_type &data () {
  298. return data_;
  299. }
  300. // Resizing
  301. BOOST_UBLAS_INLINE
  302. void resize (size_type size, bool preserve = true) {
  303. if (preserve) {
  304. self_type temporary (size, size);
  305. detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary);
  306. }
  307. else {
  308. data ().resize (triangular_type::packed_size (layout_type (), size, size));
  309. size_ = size;
  310. }
  311. }
  312. BOOST_UBLAS_INLINE
  313. void resize (size_type size1, size_type size2, bool preserve = true) {
  314. resize (BOOST_UBLAS_SAME (size1, size2), preserve);
  315. }
  316. BOOST_UBLAS_INLINE
  317. void resize_packed_preserve (size_type size) {
  318. size_ = BOOST_UBLAS_SAME (size, size);
  319. data ().resize (triangular_type::packed_size (layout_type (), size_, size_), value_type ());
  320. }
  321. // Element access
  322. BOOST_UBLAS_INLINE
  323. const_reference operator () (size_type i, size_type j) const {
  324. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  325. BOOST_UBLAS_CHECK (j < size_, bad_index ());
  326. // if (i == j)
  327. // return type_traits<value_type>::real (data () [triangular_type::element (layout_type (), i, size_, i, size_)]);
  328. // else
  329. if (triangular_type::other (i, j))
  330. return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
  331. else
  332. return type_traits<value_type>::conj (data () [triangular_type::element (layout_type (), j, size_, i, size_)]);
  333. }
  334. BOOST_UBLAS_INLINE
  335. true_reference at_element (size_type i, size_type j) {
  336. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  337. BOOST_UBLAS_CHECK (j < size_, bad_index ());
  338. BOOST_UBLAS_CHECK (triangular_type::other (i, j), bad_index ());
  339. return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
  340. }
  341. BOOST_UBLAS_INLINE
  342. reference operator () (size_type i, size_type j) {
  343. #ifndef BOOST_UBLAS_STRICT_HERMITIAN
  344. if (!triangular_type::other (i, j)) {
  345. bad_index ().raise ();
  346. // NEVER reached
  347. }
  348. return at_element (i, j);
  349. #else
  350. if (triangular_type::other (i, j))
  351. return reference (*this, i, j, data () [triangular_type::element (layout_type (), i, size_, j, size_)]);
  352. else
  353. return reference (*this, i, j, type_traits<value_type>::conj (data () [triangular_type::element (layout_type (), j, size_, i, size_)]));
  354. #endif
  355. }
  356. // Element assignemnt
  357. BOOST_UBLAS_INLINE
  358. true_reference insert_element (size_type i, size_type j, const_reference t) {
  359. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  360. BOOST_UBLAS_CHECK (j < size_, bad_index ());
  361. if (triangular_type::other (i, j)) {
  362. return (data () [triangular_type::element (layout_type (), i, size_, j, size_)] = t);
  363. } else {
  364. return (data () [triangular_type::element (layout_type (), j, size_, i, size_)] = type_traits<value_type>::conj (t));
  365. }
  366. }
  367. BOOST_UBLAS_INLINE
  368. void erase_element (size_type i, size_type j) {
  369. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  370. BOOST_UBLAS_CHECK (j < size_, bad_index ());
  371. data () [triangular_type::element (layout_type (), i, size_, j, size_)] = value_type/*zero*/();
  372. }
  373. // Zeroing
  374. BOOST_UBLAS_INLINE
  375. void clear () {
  376. std::fill (data ().begin (), data ().end (), value_type/*zero*/());
  377. }
  378. // Assignment
  379. BOOST_UBLAS_INLINE
  380. hermitian_matrix &operator = (const hermitian_matrix &m) {
  381. size_ = m.size_;
  382. data () = m.data ();
  383. return *this;
  384. }
  385. BOOST_UBLAS_INLINE
  386. hermitian_matrix &assign_temporary (hermitian_matrix &m) {
  387. swap (m);
  388. return *this;
  389. }
  390. template<class AE>
  391. BOOST_UBLAS_INLINE
  392. hermitian_matrix &operator = (const matrix_expression<AE> &ae) {
  393. self_type temporary (ae);
  394. return assign_temporary (temporary);
  395. }
  396. template<class AE>
  397. BOOST_UBLAS_INLINE
  398. hermitian_matrix &assign (const matrix_expression<AE> &ae) {
  399. matrix_assign<scalar_assign> (*this, ae);
  400. return *this;
  401. }
  402. template<class AE>
  403. BOOST_UBLAS_INLINE
  404. hermitian_matrix& operator += (const matrix_expression<AE> &ae) {
  405. self_type temporary (*this + ae);
  406. return assign_temporary (temporary);
  407. }
  408. template<class AE>
  409. BOOST_UBLAS_INLINE
  410. hermitian_matrix &plus_assign (const matrix_expression<AE> &ae) {
  411. matrix_assign<scalar_plus_assign> (*this, ae);
  412. return *this;
  413. }
  414. template<class AE>
  415. BOOST_UBLAS_INLINE
  416. hermitian_matrix& operator -= (const matrix_expression<AE> &ae) {
  417. self_type temporary (*this - ae);
  418. return assign_temporary (temporary);
  419. }
  420. template<class AE>
  421. BOOST_UBLAS_INLINE
  422. hermitian_matrix &minus_assign (const matrix_expression<AE> &ae) {
  423. matrix_assign<scalar_minus_assign> (*this, ae);
  424. return *this;
  425. }
  426. template<class AT>
  427. BOOST_UBLAS_INLINE
  428. hermitian_matrix& operator *= (const AT &at) {
  429. // Multiplication is only allowed for real scalars,
  430. // otherwise the resulting matrix isn't hermitian.
  431. // Thanks to Peter Schmitteckert for spotting this.
  432. BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
  433. matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  434. return *this;
  435. }
  436. template<class AT>
  437. BOOST_UBLAS_INLINE
  438. hermitian_matrix& operator /= (const AT &at) {
  439. // Multiplication is only allowed for real scalars,
  440. // otherwise the resulting matrix isn't hermitian.
  441. // Thanks to Peter Schmitteckert for spotting this.
  442. BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
  443. matrix_assign_scalar<scalar_divides_assign> (*this, at);
  444. return *this;
  445. }
  446. // Swapping
  447. BOOST_UBLAS_INLINE
  448. void swap (hermitian_matrix &m) {
  449. if (this != &m) {
  450. std::swap (size_, m.size_);
  451. data ().swap (m.data ());
  452. }
  453. }
  454. BOOST_UBLAS_INLINE
  455. friend void swap (hermitian_matrix &m1, hermitian_matrix &m2) {
  456. m1.swap (m2);
  457. }
  458. // Iterator types
  459. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  460. typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
  461. typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
  462. typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
  463. typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
  464. #else
  465. class const_iterator1;
  466. class iterator1;
  467. class const_iterator2;
  468. class iterator2;
  469. #endif
  470. typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  471. typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  472. typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  473. typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  474. // Element lookup
  475. BOOST_UBLAS_INLINE
  476. const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
  477. return const_iterator1 (*this, i, j);
  478. }
  479. BOOST_UBLAS_INLINE
  480. iterator1 find1 (int rank, size_type i, size_type j) {
  481. if (rank == 1)
  482. i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
  483. if (rank == 0)
  484. i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
  485. return iterator1 (*this, i, j);
  486. }
  487. BOOST_UBLAS_INLINE
  488. const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
  489. return const_iterator2 (*this, i, j);
  490. }
  491. BOOST_UBLAS_INLINE
  492. iterator2 find2 (int rank, size_type i, size_type j) {
  493. if (rank == 1)
  494. j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
  495. if (rank == 0)
  496. j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
  497. return iterator2 (*this, i, j);
  498. }
  499. // Iterators simply are indices.
  500. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  501. class const_iterator1:
  502. public container_const_reference<hermitian_matrix>,
  503. public random_access_iterator_base<packed_random_access_iterator_tag,
  504. const_iterator1, value_type> {
  505. public:
  506. typedef typename hermitian_matrix::value_type value_type;
  507. typedef typename hermitian_matrix::difference_type difference_type;
  508. typedef typename hermitian_matrix::const_reference reference;
  509. typedef const typename hermitian_matrix::pointer pointer;
  510. typedef const_iterator2 dual_iterator_type;
  511. typedef const_reverse_iterator2 dual_reverse_iterator_type;
  512. // Construction and destruction
  513. BOOST_UBLAS_INLINE
  514. const_iterator1 ():
  515. container_const_reference<self_type> (), it1_ (), it2_ () {}
  516. BOOST_UBLAS_INLINE
  517. const_iterator1 (const self_type &m, size_type it1, size_type it2):
  518. container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  519. BOOST_UBLAS_INLINE
  520. const_iterator1 (const iterator1 &it):
  521. container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
  522. // Arithmetic
  523. BOOST_UBLAS_INLINE
  524. const_iterator1 &operator ++ () {
  525. ++ it1_;
  526. return *this;
  527. }
  528. BOOST_UBLAS_INLINE
  529. const_iterator1 &operator -- () {
  530. -- it1_;
  531. return *this;
  532. }
  533. BOOST_UBLAS_INLINE
  534. const_iterator1 &operator += (difference_type n) {
  535. it1_ += n;
  536. return *this;
  537. }
  538. BOOST_UBLAS_INLINE
  539. const_iterator1 &operator -= (difference_type n) {
  540. it1_ -= n;
  541. return *this;
  542. }
  543. BOOST_UBLAS_INLINE
  544. difference_type operator - (const const_iterator1 &it) const {
  545. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  546. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  547. return it1_ - it.it1_;
  548. }
  549. // Dereference
  550. BOOST_UBLAS_INLINE
  551. const_reference operator * () const {
  552. return (*this) () (it1_, it2_);
  553. }
  554. BOOST_UBLAS_INLINE
  555. const_reference operator [] (difference_type n) const {
  556. return *(*this + n);
  557. }
  558. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  559. BOOST_UBLAS_INLINE
  560. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  561. typename self_type::
  562. #endif
  563. const_iterator2 begin () const {
  564. return (*this) ().find2 (1, it1_, 0);
  565. }
  566. BOOST_UBLAS_INLINE
  567. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  568. typename self_type::
  569. #endif
  570. const_iterator2 end () const {
  571. return (*this) ().find2 (1, it1_, (*this) ().size2 ());
  572. }
  573. BOOST_UBLAS_INLINE
  574. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  575. typename self_type::
  576. #endif
  577. const_reverse_iterator2 rbegin () const {
  578. return const_reverse_iterator2 (end ());
  579. }
  580. BOOST_UBLAS_INLINE
  581. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  582. typename self_type::
  583. #endif
  584. const_reverse_iterator2 rend () const {
  585. return const_reverse_iterator2 (begin ());
  586. }
  587. #endif
  588. // Indices
  589. BOOST_UBLAS_INLINE
  590. size_type index1 () const {
  591. return it1_;
  592. }
  593. BOOST_UBLAS_INLINE
  594. size_type index2 () const {
  595. return it2_;
  596. }
  597. // Assignment
  598. BOOST_UBLAS_INLINE
  599. const_iterator1 &operator = (const const_iterator1 &it) {
  600. container_const_reference<self_type>::assign (&it ());
  601. it1_ = it.it1_;
  602. it2_ = it.it2_;
  603. return *this;
  604. }
  605. // Comparison
  606. BOOST_UBLAS_INLINE
  607. bool operator == (const const_iterator1 &it) const {
  608. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  609. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  610. return it1_ == it.it1_;
  611. }
  612. BOOST_UBLAS_INLINE
  613. bool operator < (const const_iterator1 &it) const {
  614. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  615. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  616. return it1_ < it.it1_;
  617. }
  618. private:
  619. size_type it1_;
  620. size_type it2_;
  621. };
  622. #endif
  623. BOOST_UBLAS_INLINE
  624. const_iterator1 begin1 () const {
  625. return find1 (0, 0, 0);
  626. }
  627. BOOST_UBLAS_INLINE
  628. const_iterator1 end1 () const {
  629. return find1 (0, size_, 0);
  630. }
  631. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  632. class iterator1:
  633. public container_reference<hermitian_matrix>,
  634. public random_access_iterator_base<packed_random_access_iterator_tag,
  635. iterator1, value_type> {
  636. public:
  637. typedef typename hermitian_matrix::value_type value_type;
  638. typedef typename hermitian_matrix::difference_type difference_type;
  639. typedef typename hermitian_matrix::true_reference reference;
  640. typedef typename hermitian_matrix::pointer pointer;
  641. typedef iterator2 dual_iterator_type;
  642. typedef reverse_iterator2 dual_reverse_iterator_type;
  643. // Construction and destruction
  644. BOOST_UBLAS_INLINE
  645. iterator1 ():
  646. container_reference<self_type> (), it1_ (), it2_ () {}
  647. BOOST_UBLAS_INLINE
  648. iterator1 (self_type &m, size_type it1, size_type it2):
  649. container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  650. // Arithmetic
  651. BOOST_UBLAS_INLINE
  652. iterator1 &operator ++ () {
  653. ++ it1_;
  654. return *this;
  655. }
  656. BOOST_UBLAS_INLINE
  657. iterator1 &operator -- () {
  658. -- it1_;
  659. return *this;
  660. }
  661. BOOST_UBLAS_INLINE
  662. iterator1 &operator += (difference_type n) {
  663. it1_ += n;
  664. return *this;
  665. }
  666. BOOST_UBLAS_INLINE
  667. iterator1 &operator -= (difference_type n) {
  668. it1_ -= n;
  669. return *this;
  670. }
  671. BOOST_UBLAS_INLINE
  672. difference_type operator - (const iterator1 &it) const {
  673. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  674. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  675. return it1_ - it.it1_;
  676. }
  677. // Dereference
  678. BOOST_UBLAS_INLINE
  679. reference operator * () const {
  680. return (*this) ().at_element (it1_, it2_);
  681. }
  682. BOOST_UBLAS_INLINE
  683. reference operator [] (difference_type n) const {
  684. return *(*this + n);
  685. }
  686. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  687. BOOST_UBLAS_INLINE
  688. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  689. typename self_type::
  690. #endif
  691. iterator2 begin () const {
  692. return (*this) ().find2 (1, it1_, 0);
  693. }
  694. BOOST_UBLAS_INLINE
  695. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  696. typename self_type::
  697. #endif
  698. iterator2 end () const {
  699. return (*this) ().find2 (1, it1_, (*this) ().size2 ());
  700. }
  701. BOOST_UBLAS_INLINE
  702. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  703. typename self_type::
  704. #endif
  705. reverse_iterator2 rbegin () const {
  706. return reverse_iterator2 (end ());
  707. }
  708. BOOST_UBLAS_INLINE
  709. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  710. typename self_type::
  711. #endif
  712. reverse_iterator2 rend () const {
  713. return reverse_iterator2 (begin ());
  714. }
  715. #endif
  716. // Indices
  717. BOOST_UBLAS_INLINE
  718. size_type index1 () const {
  719. return it1_;
  720. }
  721. BOOST_UBLAS_INLINE
  722. size_type index2 () const {
  723. return it2_;
  724. }
  725. // Assignment
  726. BOOST_UBLAS_INLINE
  727. iterator1 &operator = (const iterator1 &it) {
  728. container_reference<self_type>::assign (&it ());
  729. it1_ = it.it1_;
  730. it2_ = it.it2_;
  731. return *this;
  732. }
  733. // Comparison
  734. BOOST_UBLAS_INLINE
  735. bool operator == (const iterator1 &it) const {
  736. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  737. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  738. return it1_ == it.it1_;
  739. }
  740. BOOST_UBLAS_INLINE
  741. bool operator < (const iterator1 &it) const {
  742. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  743. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  744. return it1_ < it.it1_;
  745. }
  746. private:
  747. size_type it1_;
  748. size_type it2_;
  749. friend class const_iterator1;
  750. };
  751. #endif
  752. BOOST_UBLAS_INLINE
  753. iterator1 begin1 () {
  754. return find1 (0, 0, 0);
  755. }
  756. BOOST_UBLAS_INLINE
  757. iterator1 end1 () {
  758. return find1 (0, size_, 0);
  759. }
  760. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  761. class const_iterator2:
  762. public container_const_reference<hermitian_matrix>,
  763. public random_access_iterator_base<packed_random_access_iterator_tag,
  764. const_iterator2, value_type> {
  765. public:
  766. typedef typename hermitian_matrix::value_type value_type;
  767. typedef typename hermitian_matrix::difference_type difference_type;
  768. typedef typename hermitian_matrix::const_reference reference;
  769. typedef const typename hermitian_matrix::pointer pointer;
  770. typedef const_iterator1 dual_iterator_type;
  771. typedef const_reverse_iterator1 dual_reverse_iterator_type;
  772. // Construction and destruction
  773. BOOST_UBLAS_INLINE
  774. const_iterator2 ():
  775. container_const_reference<self_type> (), it1_ (), it2_ () {}
  776. BOOST_UBLAS_INLINE
  777. const_iterator2 (const self_type &m, size_type it1, size_type it2):
  778. container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  779. BOOST_UBLAS_INLINE
  780. const_iterator2 (const iterator2 &it):
  781. container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
  782. // Arithmetic
  783. BOOST_UBLAS_INLINE
  784. const_iterator2 &operator ++ () {
  785. ++ it2_;
  786. return *this;
  787. }
  788. BOOST_UBLAS_INLINE
  789. const_iterator2 &operator -- () {
  790. -- it2_;
  791. return *this;
  792. }
  793. BOOST_UBLAS_INLINE
  794. const_iterator2 &operator += (difference_type n) {
  795. it2_ += n;
  796. return *this;
  797. }
  798. BOOST_UBLAS_INLINE
  799. const_iterator2 &operator -= (difference_type n) {
  800. it2_ -= n;
  801. return *this;
  802. }
  803. BOOST_UBLAS_INLINE
  804. difference_type operator - (const const_iterator2 &it) const {
  805. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  806. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  807. return it2_ - it.it2_;
  808. }
  809. // Dereference
  810. BOOST_UBLAS_INLINE
  811. const_reference operator * () const {
  812. return (*this) () (it1_, it2_);
  813. }
  814. BOOST_UBLAS_INLINE
  815. const_reference operator [] (difference_type n) const {
  816. return *(*this + n);
  817. }
  818. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  819. BOOST_UBLAS_INLINE
  820. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  821. typename self_type::
  822. #endif
  823. const_iterator1 begin () const {
  824. return (*this) ().find1 (1, 0, it2_);
  825. }
  826. BOOST_UBLAS_INLINE
  827. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  828. typename self_type::
  829. #endif
  830. const_iterator1 end () const {
  831. return (*this) ().find1 (1, (*this) ().size1 (), it2_);
  832. }
  833. BOOST_UBLAS_INLINE
  834. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  835. typename self_type::
  836. #endif
  837. const_reverse_iterator1 rbegin () const {
  838. return const_reverse_iterator1 (end ());
  839. }
  840. BOOST_UBLAS_INLINE
  841. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  842. typename self_type::
  843. #endif
  844. const_reverse_iterator1 rend () const {
  845. return const_reverse_iterator1 (begin ());
  846. }
  847. #endif
  848. // Indices
  849. BOOST_UBLAS_INLINE
  850. size_type index1 () const {
  851. return it1_;
  852. }
  853. BOOST_UBLAS_INLINE
  854. size_type index2 () const {
  855. return it2_;
  856. }
  857. // Assignment
  858. BOOST_UBLAS_INLINE
  859. const_iterator2 &operator = (const const_iterator2 &it) {
  860. container_const_reference<self_type>::assign (&it ());
  861. it1_ = it.it1_;
  862. it2_ = it.it2_;
  863. return *this;
  864. }
  865. // Comparison
  866. BOOST_UBLAS_INLINE
  867. bool operator == (const const_iterator2 &it) const {
  868. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  869. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  870. return it2_ == it.it2_;
  871. }
  872. BOOST_UBLAS_INLINE
  873. bool operator < (const const_iterator2 &it) const {
  874. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  875. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  876. return it2_ < it.it2_;
  877. }
  878. private:
  879. size_type it1_;
  880. size_type it2_;
  881. };
  882. #endif
  883. BOOST_UBLAS_INLINE
  884. const_iterator2 begin2 () const {
  885. return find2 (0, 0, 0);
  886. }
  887. BOOST_UBLAS_INLINE
  888. const_iterator2 end2 () const {
  889. return find2 (0, 0, size_);
  890. }
  891. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  892. class iterator2:
  893. public container_reference<hermitian_matrix>,
  894. public random_access_iterator_base<packed_random_access_iterator_tag,
  895. iterator2, value_type> {
  896. public:
  897. typedef typename hermitian_matrix::value_type value_type;
  898. typedef typename hermitian_matrix::difference_type difference_type;
  899. typedef typename hermitian_matrix::true_reference reference;
  900. typedef typename hermitian_matrix::pointer pointer;
  901. typedef iterator1 dual_iterator_type;
  902. typedef reverse_iterator1 dual_reverse_iterator_type;
  903. // Construction and destruction
  904. BOOST_UBLAS_INLINE
  905. iterator2 ():
  906. container_reference<self_type> (), it1_ (), it2_ () {}
  907. BOOST_UBLAS_INLINE
  908. iterator2 (self_type &m, size_type it1, size_type it2):
  909. container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  910. // Arithmetic
  911. BOOST_UBLAS_INLINE
  912. iterator2 &operator ++ () {
  913. ++ it2_;
  914. return *this;
  915. }
  916. BOOST_UBLAS_INLINE
  917. iterator2 &operator -- () {
  918. -- it2_;
  919. return *this;
  920. }
  921. BOOST_UBLAS_INLINE
  922. iterator2 &operator += (difference_type n) {
  923. it2_ += n;
  924. return *this;
  925. }
  926. BOOST_UBLAS_INLINE
  927. iterator2 &operator -= (difference_type n) {
  928. it2_ -= n;
  929. return *this;
  930. }
  931. BOOST_UBLAS_INLINE
  932. difference_type operator - (const iterator2 &it) const {
  933. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  934. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  935. return it2_ - it.it2_;
  936. }
  937. // Dereference
  938. BOOST_UBLAS_INLINE
  939. reference operator * () const {
  940. return (*this) ().at_element (it1_, it2_);
  941. }
  942. BOOST_UBLAS_INLINE
  943. reference operator [] (difference_type n) const {
  944. return *(*this + n);
  945. }
  946. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  947. BOOST_UBLAS_INLINE
  948. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  949. typename self_type::
  950. #endif
  951. iterator1 begin () const {
  952. return (*this) ().find1 (1, 0, it2_);
  953. }
  954. BOOST_UBLAS_INLINE
  955. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  956. typename self_type::
  957. #endif
  958. iterator1 end () const {
  959. return (*this) ().find1 (1, (*this) ().size1 (), it2_);
  960. }
  961. BOOST_UBLAS_INLINE
  962. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  963. typename self_type::
  964. #endif
  965. reverse_iterator1 rbegin () const {
  966. return reverse_iterator1 (end ());
  967. }
  968. BOOST_UBLAS_INLINE
  969. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  970. typename self_type::
  971. #endif
  972. reverse_iterator1 rend () const {
  973. return reverse_iterator1 (begin ());
  974. }
  975. #endif
  976. // Indices
  977. BOOST_UBLAS_INLINE
  978. size_type index1 () const {
  979. return it1_;
  980. }
  981. BOOST_UBLAS_INLINE
  982. size_type index2 () const {
  983. return it2_;
  984. }
  985. // Assignment
  986. BOOST_UBLAS_INLINE
  987. iterator2 &operator = (const iterator2 &it) {
  988. container_reference<self_type>::assign (&it ());
  989. it1_ = it.it1_;
  990. it2_ = it.it2_;
  991. return *this;
  992. }
  993. // Comparison
  994. BOOST_UBLAS_INLINE
  995. bool operator == (const iterator2 &it) const {
  996. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  997. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  998. return it2_ == it.it2_;
  999. }
  1000. BOOST_UBLAS_INLINE
  1001. bool operator < (const iterator2 &it) const {
  1002. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1003. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  1004. return it2_ < it.it2_;
  1005. }
  1006. private:
  1007. size_type it1_;
  1008. size_type it2_;
  1009. friend class const_iterator2;
  1010. };
  1011. #endif
  1012. BOOST_UBLAS_INLINE
  1013. iterator2 begin2 () {
  1014. return find2 (0, 0, 0);
  1015. }
  1016. BOOST_UBLAS_INLINE
  1017. iterator2 end2 () {
  1018. return find2 (0, 0, size_);
  1019. }
  1020. // Reverse iterators
  1021. BOOST_UBLAS_INLINE
  1022. const_reverse_iterator1 rbegin1 () const {
  1023. return const_reverse_iterator1 (end1 ());
  1024. }
  1025. BOOST_UBLAS_INLINE
  1026. const_reverse_iterator1 rend1 () const {
  1027. return const_reverse_iterator1 (begin1 ());
  1028. }
  1029. BOOST_UBLAS_INLINE
  1030. reverse_iterator1 rbegin1 () {
  1031. return reverse_iterator1 (end1 ());
  1032. }
  1033. BOOST_UBLAS_INLINE
  1034. reverse_iterator1 rend1 () {
  1035. return reverse_iterator1 (begin1 ());
  1036. }
  1037. BOOST_UBLAS_INLINE
  1038. const_reverse_iterator2 rbegin2 () const {
  1039. return const_reverse_iterator2 (end2 ());
  1040. }
  1041. BOOST_UBLAS_INLINE
  1042. const_reverse_iterator2 rend2 () const {
  1043. return const_reverse_iterator2 (begin2 ());
  1044. }
  1045. BOOST_UBLAS_INLINE
  1046. reverse_iterator2 rbegin2 () {
  1047. return reverse_iterator2 (end2 ());
  1048. }
  1049. BOOST_UBLAS_INLINE
  1050. reverse_iterator2 rend2 () {
  1051. return reverse_iterator2 (begin2 ());
  1052. }
  1053. private:
  1054. size_type size_;
  1055. array_type data_;
  1056. };
  1057. /** \brief A Hermitian matrix adaptator: convert a any matrix into a Hermitian matrix expression
  1058. *
  1059. * For a \f$(m\times n)\f$-dimensional matrix, the \c hermitian_adaptor will provide a hermitian matrix.
  1060. * Storage and location are based on those of the underlying matrix. This is important because
  1061. * a \c hermitian_adaptor does not copy the matrix data to a new place. Therefore, modifying values
  1062. * in a \c hermitian_adaptor matrix will also modify the underlying matrix too.
  1063. *
  1064. * \tparam M the type of matrix used to generate a hermitian matrix
  1065. */
  1066. template<class M, class TRI>
  1067. class hermitian_adaptor:
  1068. public matrix_expression<hermitian_adaptor<M, TRI> > {
  1069. typedef hermitian_adaptor<M, TRI> self_type;
  1070. typedef typename M::value_type &true_reference;
  1071. public:
  1072. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  1073. using matrix_expression<self_type>::operator ();
  1074. #endif
  1075. typedef const M const_matrix_type;
  1076. typedef M matrix_type;
  1077. typedef TRI triangular_type;
  1078. typedef typename M::size_type size_type;
  1079. typedef typename M::difference_type difference_type;
  1080. typedef typename M::value_type value_type;
  1081. typedef typename M::value_type const_reference;
  1082. #ifndef BOOST_UBLAS_STRICT_HERMITIAN
  1083. typedef typename boost::mpl::if_<boost::is_const<M>,
  1084. typename M::value_type,
  1085. typename M::reference>::type reference;
  1086. #else
  1087. typedef typename boost::mpl::if_<boost::is_const<M>,
  1088. typename M::value_type,
  1089. hermitian_matrix_element<self_type> >::type reference;
  1090. #endif
  1091. typedef typename boost::mpl::if_<boost::is_const<M>,
  1092. typename M::const_closure_type,
  1093. typename M::closure_type>::type matrix_closure_type;
  1094. typedef const self_type const_closure_type;
  1095. typedef self_type closure_type;
  1096. // Replaced by _temporary_traits to avoid type requirements on M
  1097. //typedef typename M::vector_temporary_type vector_temporary_type;
  1098. //typedef typename M::matrix_temporary_type matrix_temporary_type;
  1099. typedef typename storage_restrict_traits<typename M::storage_category,
  1100. packed_proxy_tag>::storage_category storage_category;
  1101. typedef typename M::orientation_category orientation_category;
  1102. // Construction and destruction
  1103. BOOST_UBLAS_INLINE
  1104. hermitian_adaptor (matrix_type &data):
  1105. matrix_expression<self_type> (),
  1106. data_ (data) {
  1107. BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
  1108. }
  1109. BOOST_UBLAS_INLINE
  1110. hermitian_adaptor (const hermitian_adaptor &m):
  1111. matrix_expression<self_type> (),
  1112. data_ (m.data_) {
  1113. BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
  1114. }
  1115. // Accessors
  1116. BOOST_UBLAS_INLINE
  1117. size_type size1 () const {
  1118. return data_.size1 ();
  1119. }
  1120. BOOST_UBLAS_INLINE
  1121. size_type size2 () const {
  1122. return data_.size2 ();
  1123. }
  1124. // Storage accessors
  1125. BOOST_UBLAS_INLINE
  1126. const matrix_closure_type &data () const {
  1127. return data_;
  1128. }
  1129. BOOST_UBLAS_INLINE
  1130. matrix_closure_type &data () {
  1131. return data_;
  1132. }
  1133. // Element access
  1134. #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
  1135. BOOST_UBLAS_INLINE
  1136. const_reference operator () (size_type i, size_type j) const {
  1137. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1138. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1139. // if (i == j)
  1140. // return type_traits<value_type>::real (data () (i, i));
  1141. // else
  1142. if (triangular_type::other (i, j))
  1143. return data () (i, j);
  1144. else
  1145. return type_traits<value_type>::conj (data () (j, i));
  1146. }
  1147. BOOST_UBLAS_INLINE
  1148. reference operator () (size_type i, size_type j) {
  1149. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1150. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1151. #ifndef BOOST_UBLAS_STRICT_HERMITIAN
  1152. if (triangular_type::other (i, j))
  1153. return data () (i, j);
  1154. else {
  1155. external_logic ().raise ();
  1156. return conj_ = type_traits<value_type>::conj (data () (j, i));
  1157. }
  1158. #else
  1159. if (triangular_type::other (i, j))
  1160. return reference (*this, i, j, data () (i, j));
  1161. else
  1162. return reference (*this, i, j, type_traits<value_type>::conj (data () (j, i)));
  1163. #endif
  1164. }
  1165. BOOST_UBLAS_INLINE
  1166. true_reference insert_element (size_type i, size_type j, value_type t) {
  1167. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1168. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1169. // if (i == j)
  1170. // data () (i, i) = type_traits<value_type>::real (t);
  1171. // else
  1172. if (triangular_type::other (i, j))
  1173. return data () (i, j) = t;
  1174. else
  1175. return data () (j, i) = type_traits<value_type>::conj (t);
  1176. }
  1177. #else
  1178. BOOST_UBLAS_INLINE
  1179. reference operator () (size_type i, size_type j) {
  1180. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1181. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1182. #ifndef BOOST_UBLAS_STRICT_HERMITIAN
  1183. if (triangular_type::other (i, j))
  1184. return data () (i, j);
  1185. else {
  1186. external_logic ().raise ();
  1187. return conj_ = type_traits<value_type>::conj (data () (j, i));
  1188. }
  1189. #else
  1190. if (triangular_type::other (i, j))
  1191. return reference (*this, i, j, data () (i, j));
  1192. else
  1193. return reference (*this, i, j, type_traits<value_type>::conj (data () (j, i)));
  1194. #endif
  1195. }
  1196. BOOST_UBLAS_INLINE
  1197. true_reference insert_element (size_type i, size_type j, value_type t) {
  1198. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1199. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1200. // if (i == j)
  1201. // data () (i, i) = type_traits<value_type>::real (t);
  1202. // else
  1203. if (triangular_type::other (i, j))
  1204. return data () (i, j) = t;
  1205. else
  1206. return data () (j, i) = type_traits<value_type>::conj (t);
  1207. }
  1208. #endif
  1209. // Assignment
  1210. BOOST_UBLAS_INLINE
  1211. hermitian_adaptor &operator = (const hermitian_adaptor &m) {
  1212. matrix_assign<scalar_assign, triangular_type> (*this, m);
  1213. return *this;
  1214. }
  1215. BOOST_UBLAS_INLINE
  1216. hermitian_adaptor &assign_temporary (hermitian_adaptor &m) {
  1217. *this = m;
  1218. return *this;
  1219. }
  1220. template<class AE>
  1221. BOOST_UBLAS_INLINE
  1222. hermitian_adaptor &operator = (const matrix_expression<AE> &ae) {
  1223. matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae));
  1224. return *this;
  1225. }
  1226. template<class AE>
  1227. BOOST_UBLAS_INLINE
  1228. hermitian_adaptor &assign (const matrix_expression<AE> &ae) {
  1229. matrix_assign<scalar_assign, triangular_type> (*this, ae);
  1230. return *this;
  1231. }
  1232. template<class AE>
  1233. BOOST_UBLAS_INLINE
  1234. hermitian_adaptor& operator += (const matrix_expression<AE> &ae) {
  1235. matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae));
  1236. return *this;
  1237. }
  1238. template<class AE>
  1239. BOOST_UBLAS_INLINE
  1240. hermitian_adaptor &plus_assign (const matrix_expression<AE> &ae) {
  1241. matrix_assign<scalar_plus_assign, triangular_type> (*this, ae);
  1242. return *this;
  1243. }
  1244. template<class AE>
  1245. BOOST_UBLAS_INLINE
  1246. hermitian_adaptor& operator -= (const matrix_expression<AE> &ae) {
  1247. matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae));
  1248. return *this;
  1249. }
  1250. template<class AE>
  1251. BOOST_UBLAS_INLINE
  1252. hermitian_adaptor &minus_assign (const matrix_expression<AE> &ae) {
  1253. matrix_assign<scalar_minus_assign, triangular_type> (*this, ae);
  1254. return *this;
  1255. }
  1256. template<class AT>
  1257. BOOST_UBLAS_INLINE
  1258. hermitian_adaptor& operator *= (const AT &at) {
  1259. // Multiplication is only allowed for real scalars,
  1260. // otherwise the resulting matrix isn't hermitian.
  1261. // Thanks to Peter Schmitteckert for spotting this.
  1262. BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
  1263. matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  1264. return *this;
  1265. }
  1266. template<class AT>
  1267. BOOST_UBLAS_INLINE
  1268. hermitian_adaptor& operator /= (const AT &at) {
  1269. // Multiplication is only allowed for real scalars,
  1270. // otherwise the resulting matrix isn't hermitian.
  1271. // Thanks to Peter Schmitteckert for spotting this.
  1272. BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
  1273. matrix_assign_scalar<scalar_divides_assign> (*this, at);
  1274. return *this;
  1275. }
  1276. // Closure comparison
  1277. BOOST_UBLAS_INLINE
  1278. bool same_closure (const hermitian_adaptor &ha) const {
  1279. return (*this).data ().same_closure (ha.data ());
  1280. }
  1281. // Swapping
  1282. BOOST_UBLAS_INLINE
  1283. void swap (hermitian_adaptor &m) {
  1284. if (this != &m)
  1285. matrix_swap<scalar_swap, triangular_type> (*this, m);
  1286. }
  1287. BOOST_UBLAS_INLINE
  1288. friend void swap (hermitian_adaptor &m1, hermitian_adaptor &m2) {
  1289. m1.swap (m2);
  1290. }
  1291. // Iterator types
  1292. private:
  1293. // Use matrix iterator
  1294. typedef typename M::const_iterator1 const_subiterator1_type;
  1295. typedef typename boost::mpl::if_<boost::is_const<M>,
  1296. typename M::const_iterator1,
  1297. typename M::iterator1>::type subiterator1_type;
  1298. typedef typename M::const_iterator2 const_subiterator2_type;
  1299. typedef typename boost::mpl::if_<boost::is_const<M>,
  1300. typename M::const_iterator2,
  1301. typename M::iterator2>::type subiterator2_type;
  1302. public:
  1303. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1304. typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
  1305. typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
  1306. typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
  1307. typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
  1308. #else
  1309. class const_iterator1;
  1310. class iterator1;
  1311. class const_iterator2;
  1312. class iterator2;
  1313. #endif
  1314. typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  1315. typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  1316. typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  1317. typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  1318. // Element lookup
  1319. BOOST_UBLAS_INLINE
  1320. const_iterator1 find1 (int rank, size_type i, size_type j) const {
  1321. if (triangular_type::other (i, j)) {
  1322. if (triangular_type::other (size1 (), j)) {
  1323. return const_iterator1 (*this, 0, 0,
  1324. data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j),
  1325. data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ()));
  1326. } else {
  1327. return const_iterator1 (*this, 0, 1,
  1328. data ().find1 (rank, i, j), data ().find1 (rank, j, j),
  1329. data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ()));
  1330. }
  1331. } else {
  1332. if (triangular_type::other (size1 (), j)) {
  1333. return const_iterator1 (*this, 1, 0,
  1334. data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j),
  1335. data ().find2 (rank, j, i), data ().find2 (rank, j, j));
  1336. } else {
  1337. return const_iterator1 (*this, 1, 1,
  1338. data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()),
  1339. data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ()));
  1340. }
  1341. }
  1342. }
  1343. BOOST_UBLAS_INLINE
  1344. iterator1 find1 (int rank, size_type i, size_type j) {
  1345. if (rank == 1)
  1346. i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
  1347. if (rank == 0)
  1348. i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
  1349. return iterator1 (*this, data ().find1 (rank, i, j));
  1350. }
  1351. BOOST_UBLAS_INLINE
  1352. const_iterator2 find2 (int rank, size_type i, size_type j) const {
  1353. if (triangular_type::other (i, j)) {
  1354. if (triangular_type::other (i, size2 ())) {
  1355. return const_iterator2 (*this, 1, 1,
  1356. data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()),
  1357. data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ()));
  1358. } else {
  1359. return const_iterator2 (*this, 1, 0,
  1360. data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i),
  1361. data ().find2 (rank, i, j), data ().find2 (rank, i, i));
  1362. }
  1363. } else {
  1364. if (triangular_type::other (i, size2 ())) {
  1365. return const_iterator2 (*this, 0, 1,
  1366. data ().find1 (rank, j, i), data ().find1 (rank, i, i),
  1367. data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ()));
  1368. } else {
  1369. return const_iterator2 (*this, 0, 0,
  1370. data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i),
  1371. data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ()));
  1372. }
  1373. }
  1374. }
  1375. BOOST_UBLAS_INLINE
  1376. iterator2 find2 (int rank, size_type i, size_type j) {
  1377. if (rank == 1)
  1378. j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
  1379. if (rank == 0)
  1380. j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
  1381. return iterator2 (*this, data ().find2 (rank, i, j));
  1382. }
  1383. // Iterators simply are indices.
  1384. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1385. class const_iterator1:
  1386. public container_const_reference<hermitian_adaptor>,
  1387. public random_access_iterator_base<typename iterator_restrict_traits<
  1388. typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
  1389. const_iterator1, value_type> {
  1390. public:
  1391. typedef typename const_subiterator1_type::value_type value_type;
  1392. typedef typename const_subiterator1_type::difference_type difference_type;
  1393. // FIXME no better way to not return the address of a temporary?
  1394. // typedef typename const_subiterator1_type::reference reference;
  1395. typedef typename const_subiterator1_type::value_type reference;
  1396. typedef typename const_subiterator1_type::pointer pointer;
  1397. typedef const_iterator2 dual_iterator_type;
  1398. typedef const_reverse_iterator2 dual_reverse_iterator_type;
  1399. // Construction and destruction
  1400. BOOST_UBLAS_INLINE
  1401. const_iterator1 ():
  1402. container_const_reference<self_type> (),
  1403. begin_ (-1), end_ (-1), current_ (-1),
  1404. it1_begin_ (), it1_end_ (), it1_ (),
  1405. it2_begin_ (), it2_end_ (), it2_ () {}
  1406. BOOST_UBLAS_INLINE
  1407. const_iterator1 (const self_type &m, int begin, int end,
  1408. const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
  1409. const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
  1410. container_const_reference<self_type> (m),
  1411. begin_ (begin), end_ (end), current_ (begin),
  1412. it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
  1413. it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
  1414. if (current_ == 0 && it1_ == it1_end_)
  1415. current_ = 1;
  1416. if (current_ == 1 && it2_ == it2_end_)
  1417. current_ = 0;
  1418. if ((current_ == 0 && it1_ == it1_end_) ||
  1419. (current_ == 1 && it2_ == it2_end_))
  1420. current_ = end_;
  1421. BOOST_UBLAS_CHECK (current_ == end_ ||
  1422. (current_ == 0 && it1_ != it1_end_) ||
  1423. (current_ == 1 && it2_ != it2_end_), internal_logic ());
  1424. }
  1425. // FIXME cannot compile
  1426. // iterator1 does not have these members!
  1427. BOOST_UBLAS_INLINE
  1428. const_iterator1 (const iterator1 &it):
  1429. container_const_reference<self_type> (it ()),
  1430. begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
  1431. it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
  1432. it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
  1433. BOOST_UBLAS_CHECK (current_ == end_ ||
  1434. (current_ == 0 && it1_ != it1_end_) ||
  1435. (current_ == 1 && it2_ != it2_end_), internal_logic ());
  1436. }
  1437. // Arithmetic
  1438. BOOST_UBLAS_INLINE
  1439. const_iterator1 &operator ++ () {
  1440. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1441. if (current_ == 0) {
  1442. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  1443. ++ it1_;
  1444. if (it1_ == it1_end_ && end_ == 1) {
  1445. it2_ = it2_begin_;
  1446. current_ = 1;
  1447. }
  1448. } else /* if (current_ == 1) */ {
  1449. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  1450. ++ it2_;
  1451. if (it2_ == it2_end_ && end_ == 0) {
  1452. it1_ = it1_begin_;
  1453. current_ = 0;
  1454. }
  1455. }
  1456. return *this;
  1457. }
  1458. BOOST_UBLAS_INLINE
  1459. const_iterator1 &operator -- () {
  1460. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1461. if (current_ == 0) {
  1462. if (it1_ == it1_begin_ && begin_ == 1) {
  1463. it2_ = it2_end_;
  1464. BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
  1465. -- it2_;
  1466. current_ = 1;
  1467. } else {
  1468. -- it1_;
  1469. }
  1470. } else /* if (current_ == 1) */ {
  1471. if (it2_ == it2_begin_ && begin_ == 0) {
  1472. it1_ = it1_end_;
  1473. BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
  1474. -- it1_;
  1475. current_ = 0;
  1476. } else {
  1477. -- it2_;
  1478. }
  1479. }
  1480. return *this;
  1481. }
  1482. BOOST_UBLAS_INLINE
  1483. const_iterator1 &operator += (difference_type n) {
  1484. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1485. if (current_ == 0) {
  1486. size_type d = (std::min) (n, it1_end_ - it1_);
  1487. it1_ += d;
  1488. n -= d;
  1489. if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
  1490. BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
  1491. d = (std::min) (n, it2_end_ - it2_begin_);
  1492. it2_ = it2_begin_ + d;
  1493. n -= d;
  1494. current_ = 1;
  1495. }
  1496. } else /* if (current_ == 1) */ {
  1497. size_type d = (std::min) (n, it2_end_ - it2_);
  1498. it2_ += d;
  1499. n -= d;
  1500. if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
  1501. BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
  1502. d = (std::min) (n, it1_end_ - it1_begin_);
  1503. it1_ = it1_begin_ + d;
  1504. n -= d;
  1505. current_ = 0;
  1506. }
  1507. }
  1508. BOOST_UBLAS_CHECK (n == 0, external_logic ());
  1509. return *this;
  1510. }
  1511. BOOST_UBLAS_INLINE
  1512. const_iterator1 &operator -= (difference_type n) {
  1513. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1514. if (current_ == 0) {
  1515. size_type d = (std::min) (n, it1_ - it1_begin_);
  1516. it1_ -= d;
  1517. n -= d;
  1518. if (n > 0) {
  1519. BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
  1520. d = (std::min) (n, it2_end_ - it2_begin_);
  1521. it2_ = it2_end_ - d;
  1522. n -= d;
  1523. current_ = 1;
  1524. }
  1525. } else /* if (current_ == 1) */ {
  1526. size_type d = (std::min) (n, it2_ - it2_begin_);
  1527. it2_ -= d;
  1528. n -= d;
  1529. if (n > 0) {
  1530. BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
  1531. d = (std::min) (n, it1_end_ - it1_begin_);
  1532. it1_ = it1_end_ - d;
  1533. n -= d;
  1534. current_ = 0;
  1535. }
  1536. }
  1537. BOOST_UBLAS_CHECK (n == 0, external_logic ());
  1538. return *this;
  1539. }
  1540. BOOST_UBLAS_INLINE
  1541. difference_type operator - (const const_iterator1 &it) const {
  1542. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1543. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1544. BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
  1545. BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
  1546. if (current_ == 0 && it.current_ == 0) {
  1547. return it1_ - it.it1_;
  1548. } else if (current_ == 0 && it.current_ == 1) {
  1549. if (end_ == 1 && it.end_ == 1) {
  1550. return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
  1551. } else /* if (end_ == 0 && it.end_ == 0) */ {
  1552. return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
  1553. }
  1554. } else if (current_ == 1 && it.current_ == 0) {
  1555. if (end_ == 1 && it.end_ == 1) {
  1556. return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
  1557. } else /* if (end_ == 0 && it.end_ == 0) */ {
  1558. return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
  1559. }
  1560. } else /* if (current_ == 1 && it.current_ == 1) */ {
  1561. return it2_ - it.it2_;
  1562. }
  1563. }
  1564. // Dereference
  1565. BOOST_UBLAS_INLINE
  1566. const_reference operator * () const {
  1567. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1568. if (current_ == 0) {
  1569. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  1570. if (triangular_type::other (index1 (), index2 ()))
  1571. return *it1_;
  1572. else
  1573. return type_traits<value_type>::conj (*it1_);
  1574. } else /* if (current_ == 1) */ {
  1575. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  1576. if (triangular_type::other (index1 (), index2 ()))
  1577. return *it2_;
  1578. else
  1579. return type_traits<value_type>::conj (*it2_);
  1580. }
  1581. }
  1582. BOOST_UBLAS_INLINE
  1583. const_reference operator [] (difference_type n) const {
  1584. return *(*this + n);
  1585. }
  1586. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1587. BOOST_UBLAS_INLINE
  1588. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1589. typename self_type::
  1590. #endif
  1591. const_iterator2 begin () const {
  1592. return (*this) ().find2 (1, index1 (), 0);
  1593. }
  1594. BOOST_UBLAS_INLINE
  1595. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1596. typename self_type::
  1597. #endif
  1598. const_iterator2 end () const {
  1599. return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
  1600. }
  1601. BOOST_UBLAS_INLINE
  1602. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1603. typename self_type::
  1604. #endif
  1605. const_reverse_iterator2 rbegin () const {
  1606. return const_reverse_iterator2 (end ());
  1607. }
  1608. BOOST_UBLAS_INLINE
  1609. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1610. typename self_type::
  1611. #endif
  1612. const_reverse_iterator2 rend () const {
  1613. return const_reverse_iterator2 (begin ());
  1614. }
  1615. #endif
  1616. // Indices
  1617. BOOST_UBLAS_INLINE
  1618. size_type index1 () const {
  1619. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1620. if (current_ == 0) {
  1621. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  1622. return it1_.index1 ();
  1623. } else /* if (current_ == 1) */ {
  1624. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  1625. return it2_.index2 ();
  1626. }
  1627. }
  1628. BOOST_UBLAS_INLINE
  1629. size_type index2 () const {
  1630. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1631. if (current_ == 0) {
  1632. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  1633. return it1_.index2 ();
  1634. } else /* if (current_ == 1) */ {
  1635. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  1636. return it2_.index1 ();
  1637. }
  1638. }
  1639. // Assignment
  1640. BOOST_UBLAS_INLINE
  1641. const_iterator1 &operator = (const const_iterator1 &it) {
  1642. container_const_reference<self_type>::assign (&it ());
  1643. begin_ = it.begin_;
  1644. end_ = it.end_;
  1645. current_ = it.current_;
  1646. it1_begin_ = it.it1_begin_;
  1647. it1_end_ = it.it1_end_;
  1648. it1_ = it.it1_;
  1649. it2_begin_ = it.it2_begin_;
  1650. it2_end_ = it.it2_end_;
  1651. it2_ = it.it2_;
  1652. return *this;
  1653. }
  1654. // Comparison
  1655. BOOST_UBLAS_INLINE
  1656. bool operator == (const const_iterator1 &it) const {
  1657. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1658. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1659. BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
  1660. BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
  1661. return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
  1662. (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
  1663. }
  1664. BOOST_UBLAS_INLINE
  1665. bool operator < (const const_iterator1 &it) const {
  1666. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1667. return it - *this > 0;
  1668. }
  1669. private:
  1670. int begin_;
  1671. int end_;
  1672. int current_;
  1673. const_subiterator1_type it1_begin_;
  1674. const_subiterator1_type it1_end_;
  1675. const_subiterator1_type it1_;
  1676. const_subiterator2_type it2_begin_;
  1677. const_subiterator2_type it2_end_;
  1678. const_subiterator2_type it2_;
  1679. };
  1680. #endif
  1681. BOOST_UBLAS_INLINE
  1682. const_iterator1 begin1 () const {
  1683. return find1 (0, 0, 0);
  1684. }
  1685. BOOST_UBLAS_INLINE
  1686. const_iterator1 end1 () const {
  1687. return find1 (0, size1 (), 0);
  1688. }
  1689. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1690. class iterator1:
  1691. public container_reference<hermitian_adaptor>,
  1692. public random_access_iterator_base<typename iterator_restrict_traits<
  1693. typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1694. iterator1, value_type> {
  1695. public:
  1696. typedef typename subiterator1_type::value_type value_type;
  1697. typedef typename subiterator1_type::difference_type difference_type;
  1698. typedef typename subiterator1_type::reference reference;
  1699. typedef typename subiterator1_type::pointer pointer;
  1700. typedef iterator2 dual_iterator_type;
  1701. typedef reverse_iterator2 dual_reverse_iterator_type;
  1702. // Construction and destruction
  1703. BOOST_UBLAS_INLINE
  1704. iterator1 ():
  1705. container_reference<self_type> (), it1_ () {}
  1706. BOOST_UBLAS_INLINE
  1707. iterator1 (self_type &m, const subiterator1_type &it1):
  1708. container_reference<self_type> (m), it1_ (it1) {}
  1709. // Arithmetic
  1710. BOOST_UBLAS_INLINE
  1711. iterator1 &operator ++ () {
  1712. ++ it1_;
  1713. return *this;
  1714. }
  1715. BOOST_UBLAS_INLINE
  1716. iterator1 &operator -- () {
  1717. -- it1_;
  1718. return *this;
  1719. }
  1720. BOOST_UBLAS_INLINE
  1721. iterator1 &operator += (difference_type n) {
  1722. it1_ += n;
  1723. return *this;
  1724. }
  1725. BOOST_UBLAS_INLINE
  1726. iterator1 &operator -= (difference_type n) {
  1727. it1_ -= n;
  1728. return *this;
  1729. }
  1730. BOOST_UBLAS_INLINE
  1731. difference_type operator - (const iterator1 &it) const {
  1732. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1733. return it1_ - it.it1_;
  1734. }
  1735. // Dereference
  1736. BOOST_UBLAS_INLINE
  1737. reference operator * () const {
  1738. return *it1_;
  1739. }
  1740. BOOST_UBLAS_INLINE
  1741. reference operator [] (difference_type n) const {
  1742. return *(*this + n);
  1743. }
  1744. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1745. BOOST_UBLAS_INLINE
  1746. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1747. typename self_type::
  1748. #endif
  1749. iterator2 begin () const {
  1750. return (*this) ().find2 (1, index1 (), 0);
  1751. }
  1752. BOOST_UBLAS_INLINE
  1753. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1754. typename self_type::
  1755. #endif
  1756. iterator2 end () const {
  1757. return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
  1758. }
  1759. BOOST_UBLAS_INLINE
  1760. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1761. typename self_type::
  1762. #endif
  1763. reverse_iterator2 rbegin () const {
  1764. return reverse_iterator2 (end ());
  1765. }
  1766. BOOST_UBLAS_INLINE
  1767. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1768. typename self_type::
  1769. #endif
  1770. reverse_iterator2 rend () const {
  1771. return reverse_iterator2 (begin ());
  1772. }
  1773. #endif
  1774. // Indices
  1775. BOOST_UBLAS_INLINE
  1776. size_type index1 () const {
  1777. return it1_.index1 ();
  1778. }
  1779. BOOST_UBLAS_INLINE
  1780. size_type index2 () const {
  1781. return it1_.index2 ();
  1782. }
  1783. // Assignment
  1784. BOOST_UBLAS_INLINE
  1785. iterator1 &operator = (const iterator1 &it) {
  1786. container_reference<self_type>::assign (&it ());
  1787. it1_ = it.it1_;
  1788. return *this;
  1789. }
  1790. // Comparison
  1791. BOOST_UBLAS_INLINE
  1792. bool operator == (const iterator1 &it) const {
  1793. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1794. return it1_ == it.it1_;
  1795. }
  1796. BOOST_UBLAS_INLINE
  1797. bool operator < (const iterator1 &it) const {
  1798. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1799. return it1_ < it.it1_;
  1800. }
  1801. private:
  1802. subiterator1_type it1_;
  1803. friend class const_iterator1;
  1804. };
  1805. #endif
  1806. BOOST_UBLAS_INLINE
  1807. iterator1 begin1 () {
  1808. return find1 (0, 0, 0);
  1809. }
  1810. BOOST_UBLAS_INLINE
  1811. iterator1 end1 () {
  1812. return find1 (0, size1 (), 0);
  1813. }
  1814. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1815. class const_iterator2:
  1816. public container_const_reference<hermitian_adaptor>,
  1817. public random_access_iterator_base<typename iterator_restrict_traits<
  1818. typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
  1819. const_iterator2, value_type> {
  1820. public:
  1821. typedef typename const_subiterator2_type::value_type value_type;
  1822. typedef typename const_subiterator2_type::difference_type difference_type;
  1823. // FIXME no better way to not return the address of a temporary?
  1824. // typedef typename const_subiterator2_type::reference reference;
  1825. typedef typename const_subiterator2_type::value_type reference;
  1826. typedef typename const_subiterator2_type::pointer pointer;
  1827. typedef const_iterator1 dual_iterator_type;
  1828. typedef const_reverse_iterator1 dual_reverse_iterator_type;
  1829. // Construction and destruction
  1830. BOOST_UBLAS_INLINE
  1831. const_iterator2 ():
  1832. container_const_reference<self_type> (),
  1833. begin_ (-1), end_ (-1), current_ (-1),
  1834. it1_begin_ (), it1_end_ (), it1_ (),
  1835. it2_begin_ (), it2_end_ (), it2_ () {}
  1836. BOOST_UBLAS_INLINE
  1837. const_iterator2 (const self_type &m, int begin, int end,
  1838. const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
  1839. const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
  1840. container_const_reference<self_type> (m),
  1841. begin_ (begin), end_ (end), current_ (begin),
  1842. it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
  1843. it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
  1844. if (current_ == 0 && it1_ == it1_end_)
  1845. current_ = 1;
  1846. if (current_ == 1 && it2_ == it2_end_)
  1847. current_ = 0;
  1848. if ((current_ == 0 && it1_ == it1_end_) ||
  1849. (current_ == 1 && it2_ == it2_end_))
  1850. current_ = end_;
  1851. BOOST_UBLAS_CHECK (current_ == end_ ||
  1852. (current_ == 0 && it1_ != it1_end_) ||
  1853. (current_ == 1 && it2_ != it2_end_), internal_logic ());
  1854. }
  1855. // FIXME cannot compiler
  1856. // iterator2 does not have these members!
  1857. BOOST_UBLAS_INLINE
  1858. const_iterator2 (const iterator2 &it):
  1859. container_const_reference<self_type> (it ()),
  1860. begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
  1861. it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
  1862. it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
  1863. BOOST_UBLAS_CHECK (current_ == end_ ||
  1864. (current_ == 0 && it1_ != it1_end_) ||
  1865. (current_ == 1 && it2_ != it2_end_), internal_logic ());
  1866. }
  1867. // Arithmetic
  1868. BOOST_UBLAS_INLINE
  1869. const_iterator2 &operator ++ () {
  1870. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1871. if (current_ == 0) {
  1872. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  1873. ++ it1_;
  1874. if (it1_ == it1_end_ && end_ == 1) {
  1875. it2_ = it2_begin_;
  1876. current_ = 1;
  1877. }
  1878. } else /* if (current_ == 1) */ {
  1879. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  1880. ++ it2_;
  1881. if (it2_ == it2_end_ && end_ == 0) {
  1882. it1_ = it1_begin_;
  1883. current_ = 0;
  1884. }
  1885. }
  1886. return *this;
  1887. }
  1888. BOOST_UBLAS_INLINE
  1889. const_iterator2 &operator -- () {
  1890. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1891. if (current_ == 0) {
  1892. if (it1_ == it1_begin_ && begin_ == 1) {
  1893. it2_ = it2_end_;
  1894. BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
  1895. -- it2_;
  1896. current_ = 1;
  1897. } else {
  1898. -- it1_;
  1899. }
  1900. } else /* if (current_ == 1) */ {
  1901. if (it2_ == it2_begin_ && begin_ == 0) {
  1902. it1_ = it1_end_;
  1903. BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
  1904. -- it1_;
  1905. current_ = 0;
  1906. } else {
  1907. -- it2_;
  1908. }
  1909. }
  1910. return *this;
  1911. }
  1912. BOOST_UBLAS_INLINE
  1913. const_iterator2 &operator += (difference_type n) {
  1914. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1915. if (current_ == 0) {
  1916. size_type d = (std::min) (n, it1_end_ - it1_);
  1917. it1_ += d;
  1918. n -= d;
  1919. if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
  1920. BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
  1921. d = (std::min) (n, it2_end_ - it2_begin_);
  1922. it2_ = it2_begin_ + d;
  1923. n -= d;
  1924. current_ = 1;
  1925. }
  1926. } else /* if (current_ == 1) */ {
  1927. size_type d = (std::min) (n, it2_end_ - it2_);
  1928. it2_ += d;
  1929. n -= d;
  1930. if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
  1931. BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
  1932. d = (std::min) (n, it1_end_ - it1_begin_);
  1933. it1_ = it1_begin_ + d;
  1934. n -= d;
  1935. current_ = 0;
  1936. }
  1937. }
  1938. BOOST_UBLAS_CHECK (n == 0, external_logic ());
  1939. return *this;
  1940. }
  1941. BOOST_UBLAS_INLINE
  1942. const_iterator2 &operator -= (difference_type n) {
  1943. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1944. if (current_ == 0) {
  1945. size_type d = (std::min) (n, it1_ - it1_begin_);
  1946. it1_ -= d;
  1947. n -= d;
  1948. if (n > 0) {
  1949. BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
  1950. d = (std::min) (n, it2_end_ - it2_begin_);
  1951. it2_ = it2_end_ - d;
  1952. n -= d;
  1953. current_ = 1;
  1954. }
  1955. } else /* if (current_ == 1) */ {
  1956. size_type d = (std::min) (n, it2_ - it2_begin_);
  1957. it2_ -= d;
  1958. n -= d;
  1959. if (n > 0) {
  1960. BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
  1961. d = (std::min) (n, it1_end_ - it1_begin_);
  1962. it1_ = it1_end_ - d;
  1963. n -= d;
  1964. current_ = 0;
  1965. }
  1966. }
  1967. BOOST_UBLAS_CHECK (n == 0, external_logic ());
  1968. return *this;
  1969. }
  1970. BOOST_UBLAS_INLINE
  1971. difference_type operator - (const const_iterator2 &it) const {
  1972. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1973. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1974. BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
  1975. BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
  1976. if (current_ == 0 && it.current_ == 0) {
  1977. return it1_ - it.it1_;
  1978. } else if (current_ == 0 && it.current_ == 1) {
  1979. if (end_ == 1 && it.end_ == 1) {
  1980. return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
  1981. } else /* if (end_ == 0 && it.end_ == 0) */ {
  1982. return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
  1983. }
  1984. } else if (current_ == 1 && it.current_ == 0) {
  1985. if (end_ == 1 && it.end_ == 1) {
  1986. return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
  1987. } else /* if (end_ == 0 && it.end_ == 0) */ {
  1988. return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
  1989. }
  1990. } else /* if (current_ == 1 && it.current_ == 1) */ {
  1991. return it2_ - it.it2_;
  1992. }
  1993. }
  1994. // Dereference
  1995. BOOST_UBLAS_INLINE
  1996. const_reference operator * () const {
  1997. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1998. if (current_ == 0) {
  1999. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  2000. if (triangular_type::other (index1 (), index2 ()))
  2001. return *it1_;
  2002. else
  2003. return type_traits<value_type>::conj (*it1_);
  2004. } else /* if (current_ == 1) */ {
  2005. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  2006. if (triangular_type::other (index1 (), index2 ()))
  2007. return *it2_;
  2008. else
  2009. return type_traits<value_type>::conj (*it2_);
  2010. }
  2011. }
  2012. BOOST_UBLAS_INLINE
  2013. const_reference operator [] (difference_type n) const {
  2014. return *(*this + n);
  2015. }
  2016. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  2017. BOOST_UBLAS_INLINE
  2018. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2019. typename self_type::
  2020. #endif
  2021. const_iterator1 begin () const {
  2022. return (*this) ().find1 (1, 0, index2 ());
  2023. }
  2024. BOOST_UBLAS_INLINE
  2025. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2026. typename self_type::
  2027. #endif
  2028. const_iterator1 end () const {
  2029. return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
  2030. }
  2031. BOOST_UBLAS_INLINE
  2032. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2033. typename self_type::
  2034. #endif
  2035. const_reverse_iterator1 rbegin () const {
  2036. return const_reverse_iterator1 (end ());
  2037. }
  2038. BOOST_UBLAS_INLINE
  2039. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2040. typename self_type::
  2041. #endif
  2042. const_reverse_iterator1 rend () const {
  2043. return const_reverse_iterator1 (begin ());
  2044. }
  2045. #endif
  2046. // Indices
  2047. BOOST_UBLAS_INLINE
  2048. size_type index1 () const {
  2049. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  2050. if (current_ == 0) {
  2051. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  2052. return it1_.index2 ();
  2053. } else /* if (current_ == 1) */ {
  2054. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  2055. return it2_.index1 ();
  2056. }
  2057. }
  2058. BOOST_UBLAS_INLINE
  2059. size_type index2 () const {
  2060. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  2061. if (current_ == 0) {
  2062. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  2063. return it1_.index1 ();
  2064. } else /* if (current_ == 1) */ {
  2065. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  2066. return it2_.index2 ();
  2067. }
  2068. }
  2069. // Assignment
  2070. BOOST_UBLAS_INLINE
  2071. const_iterator2 &operator = (const const_iterator2 &it) {
  2072. container_const_reference<self_type>::assign (&it ());
  2073. begin_ = it.begin_;
  2074. end_ = it.end_;
  2075. current_ = it.current_;
  2076. it1_begin_ = it.it1_begin_;
  2077. it1_end_ = it.it1_end_;
  2078. it1_ = it.it1_;
  2079. it2_begin_ = it.it2_begin_;
  2080. it2_end_ = it.it2_end_;
  2081. it2_ = it.it2_;
  2082. return *this;
  2083. }
  2084. // Comparison
  2085. BOOST_UBLAS_INLINE
  2086. bool operator == (const const_iterator2 &it) const {
  2087. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2088. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  2089. BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
  2090. BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
  2091. return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
  2092. (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
  2093. }
  2094. BOOST_UBLAS_INLINE
  2095. bool operator < (const const_iterator2 &it) const {
  2096. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2097. return it - *this > 0;
  2098. }
  2099. private:
  2100. int begin_;
  2101. int end_;
  2102. int current_;
  2103. const_subiterator1_type it1_begin_;
  2104. const_subiterator1_type it1_end_;
  2105. const_subiterator1_type it1_;
  2106. const_subiterator2_type it2_begin_;
  2107. const_subiterator2_type it2_end_;
  2108. const_subiterator2_type it2_;
  2109. };
  2110. #endif
  2111. BOOST_UBLAS_INLINE
  2112. const_iterator2 begin2 () const {
  2113. return find2 (0, 0, 0);
  2114. }
  2115. BOOST_UBLAS_INLINE
  2116. const_iterator2 end2 () const {
  2117. return find2 (0, 0, size2 ());
  2118. }
  2119. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  2120. class iterator2:
  2121. public container_reference<hermitian_adaptor>,
  2122. public random_access_iterator_base<typename iterator_restrict_traits<
  2123. typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  2124. iterator2, value_type> {
  2125. public:
  2126. typedef typename subiterator2_type::value_type value_type;
  2127. typedef typename subiterator2_type::difference_type difference_type;
  2128. typedef typename subiterator2_type::reference reference;
  2129. typedef typename subiterator2_type::pointer pointer;
  2130. typedef iterator1 dual_iterator_type;
  2131. typedef reverse_iterator1 dual_reverse_iterator_type;
  2132. // Construction and destruction
  2133. BOOST_UBLAS_INLINE
  2134. iterator2 ():
  2135. container_reference<self_type> (), it2_ () {}
  2136. BOOST_UBLAS_INLINE
  2137. iterator2 (self_type &m, const subiterator2_type &it2):
  2138. container_reference<self_type> (m), it2_ (it2) {}
  2139. // Arithmetic
  2140. BOOST_UBLAS_INLINE
  2141. iterator2 &operator ++ () {
  2142. ++ it2_;
  2143. return *this;
  2144. }
  2145. BOOST_UBLAS_INLINE
  2146. iterator2 &operator -- () {
  2147. -- it2_;
  2148. return *this;
  2149. }
  2150. BOOST_UBLAS_INLINE
  2151. iterator2 &operator += (difference_type n) {
  2152. it2_ += n;
  2153. return *this;
  2154. }
  2155. BOOST_UBLAS_INLINE
  2156. iterator2 &operator -= (difference_type n) {
  2157. it2_ -= n;
  2158. return *this;
  2159. }
  2160. BOOST_UBLAS_INLINE
  2161. difference_type operator - (const iterator2 &it) const {
  2162. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2163. return it2_ - it.it2_;
  2164. }
  2165. // Dereference
  2166. BOOST_UBLAS_INLINE
  2167. reference operator * () const {
  2168. return *it2_;
  2169. }
  2170. BOOST_UBLAS_INLINE
  2171. reference operator [] (difference_type n) const {
  2172. return *(*this + n);
  2173. }
  2174. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  2175. BOOST_UBLAS_INLINE
  2176. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2177. typename self_type::
  2178. #endif
  2179. iterator1 begin () const {
  2180. return (*this) ().find1 (1, 0, index2 ());
  2181. }
  2182. BOOST_UBLAS_INLINE
  2183. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2184. typename self_type::
  2185. #endif
  2186. iterator1 end () const {
  2187. return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
  2188. }
  2189. BOOST_UBLAS_INLINE
  2190. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2191. typename self_type::
  2192. #endif
  2193. reverse_iterator1 rbegin () const {
  2194. return reverse_iterator1 (end ());
  2195. }
  2196. BOOST_UBLAS_INLINE
  2197. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2198. typename self_type::
  2199. #endif
  2200. reverse_iterator1 rend () const {
  2201. return reverse_iterator1 (begin ());
  2202. }
  2203. #endif
  2204. // Indices
  2205. BOOST_UBLAS_INLINE
  2206. size_type index1 () const {
  2207. return it2_.index1 ();
  2208. }
  2209. BOOST_UBLAS_INLINE
  2210. size_type index2 () const {
  2211. return it2_.index2 ();
  2212. }
  2213. // Assignment
  2214. BOOST_UBLAS_INLINE
  2215. iterator2 &operator = (const iterator2 &it) {
  2216. container_reference<self_type>::assign (&it ());
  2217. it2_ = it.it2_;
  2218. return *this;
  2219. }
  2220. // Comparison
  2221. BOOST_UBLAS_INLINE
  2222. bool operator == (const iterator2 &it) const {
  2223. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2224. return it2_ == it.it2_;
  2225. }
  2226. BOOST_UBLAS_INLINE
  2227. bool operator < (const iterator2 &it) const {
  2228. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2229. return it2_ < it.it2_;
  2230. }
  2231. private:
  2232. subiterator2_type it2_;
  2233. friend class const_iterator2;
  2234. };
  2235. #endif
  2236. BOOST_UBLAS_INLINE
  2237. iterator2 begin2 () {
  2238. return find2 (0, 0, 0);
  2239. }
  2240. BOOST_UBLAS_INLINE
  2241. iterator2 end2 () {
  2242. return find2 (0, 0, size2 ());
  2243. }
  2244. // Reverse iterators
  2245. BOOST_UBLAS_INLINE
  2246. const_reverse_iterator1 rbegin1 () const {
  2247. return const_reverse_iterator1 (end1 ());
  2248. }
  2249. BOOST_UBLAS_INLINE
  2250. const_reverse_iterator1 rend1 () const {
  2251. return const_reverse_iterator1 (begin1 ());
  2252. }
  2253. BOOST_UBLAS_INLINE
  2254. reverse_iterator1 rbegin1 () {
  2255. return reverse_iterator1 (end1 ());
  2256. }
  2257. BOOST_UBLAS_INLINE
  2258. reverse_iterator1 rend1 () {
  2259. return reverse_iterator1 (begin1 ());
  2260. }
  2261. BOOST_UBLAS_INLINE
  2262. const_reverse_iterator2 rbegin2 () const {
  2263. return const_reverse_iterator2 (end2 ());
  2264. }
  2265. BOOST_UBLAS_INLINE
  2266. const_reverse_iterator2 rend2 () const {
  2267. return const_reverse_iterator2 (begin2 ());
  2268. }
  2269. BOOST_UBLAS_INLINE
  2270. reverse_iterator2 rbegin2 () {
  2271. return reverse_iterator2 (end2 ());
  2272. }
  2273. BOOST_UBLAS_INLINE
  2274. reverse_iterator2 rend2 () {
  2275. return reverse_iterator2 (begin2 ());
  2276. }
  2277. private:
  2278. matrix_closure_type data_;
  2279. static value_type conj_;
  2280. };
  2281. template<class M, class TRI>
  2282. typename hermitian_adaptor<M, TRI>::value_type hermitian_adaptor<M, TRI>::conj_;
  2283. // Specialization for temporary_traits
  2284. template <class M, class TRI>
  2285. struct vector_temporary_traits< hermitian_adaptor<M, TRI> >
  2286. : vector_temporary_traits< M > {} ;
  2287. template <class M, class TRI>
  2288. struct vector_temporary_traits< const hermitian_adaptor<M, TRI> >
  2289. : vector_temporary_traits< M > {} ;
  2290. template <class M, class TRI>
  2291. struct matrix_temporary_traits< hermitian_adaptor<M, TRI> >
  2292. : matrix_temporary_traits< M > {} ;
  2293. template <class M, class TRI>
  2294. struct matrix_temporary_traits< const hermitian_adaptor<M, TRI> >
  2295. : matrix_temporary_traits< M > {} ;
  2296. }}}
  2297. #endif