hermitian.hpp 100 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633
  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 cbegin () const {
  571. return begin ();
  572. }
  573. BOOST_UBLAS_INLINE
  574. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  575. typename self_type::
  576. #endif
  577. const_iterator2 end () const {
  578. return (*this) ().find2 (1, it1_, (*this) ().size2 ());
  579. }
  580. BOOST_UBLAS_INLINE
  581. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  582. typename self_type::
  583. #endif
  584. const_iterator2 cend () const {
  585. return end ();
  586. }
  587. BOOST_UBLAS_INLINE
  588. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  589. typename self_type::
  590. #endif
  591. const_reverse_iterator2 rbegin () const {
  592. return const_reverse_iterator2 (end ());
  593. }
  594. BOOST_UBLAS_INLINE
  595. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  596. typename self_type::
  597. #endif
  598. const_reverse_iterator2 crbegin () const {
  599. return rbegin ();
  600. }
  601. BOOST_UBLAS_INLINE
  602. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  603. typename self_type::
  604. #endif
  605. const_reverse_iterator2 rend () const {
  606. return const_reverse_iterator2 (begin ());
  607. }
  608. BOOST_UBLAS_INLINE
  609. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  610. typename self_type::
  611. #endif
  612. const_reverse_iterator2 crend () const {
  613. return rend ();
  614. }
  615. #endif
  616. // Indices
  617. BOOST_UBLAS_INLINE
  618. size_type index1 () const {
  619. return it1_;
  620. }
  621. BOOST_UBLAS_INLINE
  622. size_type index2 () const {
  623. return it2_;
  624. }
  625. // Assignment
  626. BOOST_UBLAS_INLINE
  627. const_iterator1 &operator = (const const_iterator1 &it) {
  628. container_const_reference<self_type>::assign (&it ());
  629. it1_ = it.it1_;
  630. it2_ = it.it2_;
  631. return *this;
  632. }
  633. // Comparison
  634. BOOST_UBLAS_INLINE
  635. bool operator == (const const_iterator1 &it) const {
  636. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  637. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  638. return it1_ == it.it1_;
  639. }
  640. BOOST_UBLAS_INLINE
  641. bool operator < (const const_iterator1 &it) const {
  642. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  643. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  644. return it1_ < it.it1_;
  645. }
  646. private:
  647. size_type it1_;
  648. size_type it2_;
  649. };
  650. #endif
  651. BOOST_UBLAS_INLINE
  652. const_iterator1 begin1 () const {
  653. return find1 (0, 0, 0);
  654. }
  655. BOOST_UBLAS_INLINE
  656. const_iterator1 cbegin1 () const {
  657. return begin1 ();
  658. }
  659. BOOST_UBLAS_INLINE
  660. const_iterator1 end1 () const {
  661. return find1 (0, size_, 0);
  662. }
  663. BOOST_UBLAS_INLINE
  664. const_iterator1 cend1 () const {
  665. return end1 ();
  666. }
  667. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  668. class iterator1:
  669. public container_reference<hermitian_matrix>,
  670. public random_access_iterator_base<packed_random_access_iterator_tag,
  671. iterator1, value_type> {
  672. public:
  673. typedef typename hermitian_matrix::value_type value_type;
  674. typedef typename hermitian_matrix::difference_type difference_type;
  675. typedef typename hermitian_matrix::true_reference reference;
  676. typedef typename hermitian_matrix::pointer pointer;
  677. typedef iterator2 dual_iterator_type;
  678. typedef reverse_iterator2 dual_reverse_iterator_type;
  679. // Construction and destruction
  680. BOOST_UBLAS_INLINE
  681. iterator1 ():
  682. container_reference<self_type> (), it1_ (), it2_ () {}
  683. BOOST_UBLAS_INLINE
  684. iterator1 (self_type &m, size_type it1, size_type it2):
  685. container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  686. // Arithmetic
  687. BOOST_UBLAS_INLINE
  688. iterator1 &operator ++ () {
  689. ++ it1_;
  690. return *this;
  691. }
  692. BOOST_UBLAS_INLINE
  693. iterator1 &operator -- () {
  694. -- it1_;
  695. return *this;
  696. }
  697. BOOST_UBLAS_INLINE
  698. iterator1 &operator += (difference_type n) {
  699. it1_ += n;
  700. return *this;
  701. }
  702. BOOST_UBLAS_INLINE
  703. iterator1 &operator -= (difference_type n) {
  704. it1_ -= n;
  705. return *this;
  706. }
  707. BOOST_UBLAS_INLINE
  708. difference_type operator - (const iterator1 &it) const {
  709. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  710. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  711. return it1_ - it.it1_;
  712. }
  713. // Dereference
  714. BOOST_UBLAS_INLINE
  715. reference operator * () const {
  716. return (*this) ().at_element (it1_, it2_);
  717. }
  718. BOOST_UBLAS_INLINE
  719. reference operator [] (difference_type n) const {
  720. return *(*this + n);
  721. }
  722. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  723. BOOST_UBLAS_INLINE
  724. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  725. typename self_type::
  726. #endif
  727. iterator2 begin () const {
  728. return (*this) ().find2 (1, it1_, 0);
  729. }
  730. BOOST_UBLAS_INLINE
  731. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  732. typename self_type::
  733. #endif
  734. iterator2 end () const {
  735. return (*this) ().find2 (1, it1_, (*this) ().size2 ());
  736. }
  737. BOOST_UBLAS_INLINE
  738. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  739. typename self_type::
  740. #endif
  741. reverse_iterator2 rbegin () const {
  742. return reverse_iterator2 (end ());
  743. }
  744. BOOST_UBLAS_INLINE
  745. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  746. typename self_type::
  747. #endif
  748. reverse_iterator2 rend () const {
  749. return reverse_iterator2 (begin ());
  750. }
  751. #endif
  752. // Indices
  753. BOOST_UBLAS_INLINE
  754. size_type index1 () const {
  755. return it1_;
  756. }
  757. BOOST_UBLAS_INLINE
  758. size_type index2 () const {
  759. return it2_;
  760. }
  761. // Assignment
  762. BOOST_UBLAS_INLINE
  763. iterator1 &operator = (const iterator1 &it) {
  764. container_reference<self_type>::assign (&it ());
  765. it1_ = it.it1_;
  766. it2_ = it.it2_;
  767. return *this;
  768. }
  769. // Comparison
  770. BOOST_UBLAS_INLINE
  771. bool operator == (const iterator1 &it) const {
  772. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  773. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  774. return it1_ == it.it1_;
  775. }
  776. BOOST_UBLAS_INLINE
  777. bool operator < (const iterator1 &it) const {
  778. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  779. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  780. return it1_ < it.it1_;
  781. }
  782. private:
  783. size_type it1_;
  784. size_type it2_;
  785. friend class const_iterator1;
  786. };
  787. #endif
  788. BOOST_UBLAS_INLINE
  789. iterator1 begin1 () {
  790. return find1 (0, 0, 0);
  791. }
  792. BOOST_UBLAS_INLINE
  793. iterator1 end1 () {
  794. return find1 (0, size_, 0);
  795. }
  796. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  797. class const_iterator2:
  798. public container_const_reference<hermitian_matrix>,
  799. public random_access_iterator_base<packed_random_access_iterator_tag,
  800. const_iterator2, value_type> {
  801. public:
  802. typedef typename hermitian_matrix::value_type value_type;
  803. typedef typename hermitian_matrix::difference_type difference_type;
  804. typedef typename hermitian_matrix::const_reference reference;
  805. typedef const typename hermitian_matrix::pointer pointer;
  806. typedef const_iterator1 dual_iterator_type;
  807. typedef const_reverse_iterator1 dual_reverse_iterator_type;
  808. // Construction and destruction
  809. BOOST_UBLAS_INLINE
  810. const_iterator2 ():
  811. container_const_reference<self_type> (), it1_ (), it2_ () {}
  812. BOOST_UBLAS_INLINE
  813. const_iterator2 (const self_type &m, size_type it1, size_type it2):
  814. container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  815. BOOST_UBLAS_INLINE
  816. const_iterator2 (const iterator2 &it):
  817. container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
  818. // Arithmetic
  819. BOOST_UBLAS_INLINE
  820. const_iterator2 &operator ++ () {
  821. ++ it2_;
  822. return *this;
  823. }
  824. BOOST_UBLAS_INLINE
  825. const_iterator2 &operator -- () {
  826. -- it2_;
  827. return *this;
  828. }
  829. BOOST_UBLAS_INLINE
  830. const_iterator2 &operator += (difference_type n) {
  831. it2_ += n;
  832. return *this;
  833. }
  834. BOOST_UBLAS_INLINE
  835. const_iterator2 &operator -= (difference_type n) {
  836. it2_ -= n;
  837. return *this;
  838. }
  839. BOOST_UBLAS_INLINE
  840. difference_type operator - (const const_iterator2 &it) const {
  841. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  842. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  843. return it2_ - it.it2_;
  844. }
  845. // Dereference
  846. BOOST_UBLAS_INLINE
  847. const_reference operator * () const {
  848. return (*this) () (it1_, it2_);
  849. }
  850. BOOST_UBLAS_INLINE
  851. const_reference operator [] (difference_type n) const {
  852. return *(*this + n);
  853. }
  854. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  855. BOOST_UBLAS_INLINE
  856. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  857. typename self_type::
  858. #endif
  859. const_iterator1 begin () const {
  860. return (*this) ().find1 (1, 0, it2_);
  861. }
  862. BOOST_UBLAS_INLINE
  863. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  864. typename self_type::
  865. #endif
  866. const_iterator1 cbegin () const {
  867. return begin ();
  868. }
  869. BOOST_UBLAS_INLINE
  870. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  871. typename self_type::
  872. #endif
  873. const_iterator1 end () const {
  874. return (*this) ().find1 (1, (*this) ().size1 (), it2_);
  875. }
  876. BOOST_UBLAS_INLINE
  877. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  878. typename self_type::
  879. #endif
  880. const_iterator1 cend () const {
  881. return end ();
  882. }
  883. BOOST_UBLAS_INLINE
  884. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  885. typename self_type::
  886. #endif
  887. const_reverse_iterator1 rbegin () const {
  888. return const_reverse_iterator1 (end ());
  889. }
  890. BOOST_UBLAS_INLINE
  891. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  892. typename self_type::
  893. #endif
  894. const_iterator1 crbegin () const {
  895. return rbegin ();
  896. }
  897. BOOST_UBLAS_INLINE
  898. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  899. typename self_type::
  900. #endif
  901. const_reverse_iterator1 rend () const {
  902. return const_reverse_iterator1 (begin ());
  903. }
  904. BOOST_UBLAS_INLINE
  905. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  906. typename self_type::
  907. #endif
  908. const_iterator1 crend () const {
  909. return rend ();
  910. }
  911. #endif
  912. // Indices
  913. BOOST_UBLAS_INLINE
  914. size_type index1 () const {
  915. return it1_;
  916. }
  917. BOOST_UBLAS_INLINE
  918. size_type index2 () const {
  919. return it2_;
  920. }
  921. // Assignment
  922. BOOST_UBLAS_INLINE
  923. const_iterator2 &operator = (const const_iterator2 &it) {
  924. container_const_reference<self_type>::assign (&it ());
  925. it1_ = it.it1_;
  926. it2_ = it.it2_;
  927. return *this;
  928. }
  929. // Comparison
  930. BOOST_UBLAS_INLINE
  931. bool operator == (const const_iterator2 &it) const {
  932. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  933. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  934. return it2_ == it.it2_;
  935. }
  936. BOOST_UBLAS_INLINE
  937. bool operator < (const const_iterator2 &it) const {
  938. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  939. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  940. return it2_ < it.it2_;
  941. }
  942. private:
  943. size_type it1_;
  944. size_type it2_;
  945. };
  946. #endif
  947. BOOST_UBLAS_INLINE
  948. const_iterator2 begin2 () const {
  949. return find2 (0, 0, 0);
  950. }
  951. BOOST_UBLAS_INLINE
  952. const_iterator2 cbegin2 () const {
  953. return begin2 ();
  954. }
  955. BOOST_UBLAS_INLINE
  956. const_iterator2 end2 () const {
  957. return find2 (0, 0, size_);
  958. }
  959. BOOST_UBLAS_INLINE
  960. const_iterator2 cend2 () const {
  961. return end2 ();
  962. }
  963. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  964. class iterator2:
  965. public container_reference<hermitian_matrix>,
  966. public random_access_iterator_base<packed_random_access_iterator_tag,
  967. iterator2, value_type> {
  968. public:
  969. typedef typename hermitian_matrix::value_type value_type;
  970. typedef typename hermitian_matrix::difference_type difference_type;
  971. typedef typename hermitian_matrix::true_reference reference;
  972. typedef typename hermitian_matrix::pointer pointer;
  973. typedef iterator1 dual_iterator_type;
  974. typedef reverse_iterator1 dual_reverse_iterator_type;
  975. // Construction and destruction
  976. BOOST_UBLAS_INLINE
  977. iterator2 ():
  978. container_reference<self_type> (), it1_ (), it2_ () {}
  979. BOOST_UBLAS_INLINE
  980. iterator2 (self_type &m, size_type it1, size_type it2):
  981. container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
  982. // Arithmetic
  983. BOOST_UBLAS_INLINE
  984. iterator2 &operator ++ () {
  985. ++ it2_;
  986. return *this;
  987. }
  988. BOOST_UBLAS_INLINE
  989. iterator2 &operator -- () {
  990. -- it2_;
  991. return *this;
  992. }
  993. BOOST_UBLAS_INLINE
  994. iterator2 &operator += (difference_type n) {
  995. it2_ += n;
  996. return *this;
  997. }
  998. BOOST_UBLAS_INLINE
  999. iterator2 &operator -= (difference_type n) {
  1000. it2_ -= n;
  1001. return *this;
  1002. }
  1003. BOOST_UBLAS_INLINE
  1004. difference_type operator - (const iterator2 &it) const {
  1005. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1006. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  1007. return it2_ - it.it2_;
  1008. }
  1009. // Dereference
  1010. BOOST_UBLAS_INLINE
  1011. reference operator * () const {
  1012. return (*this) ().at_element (it1_, it2_);
  1013. }
  1014. BOOST_UBLAS_INLINE
  1015. reference operator [] (difference_type n) const {
  1016. return *(*this + n);
  1017. }
  1018. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1019. BOOST_UBLAS_INLINE
  1020. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1021. typename self_type::
  1022. #endif
  1023. iterator1 begin () const {
  1024. return (*this) ().find1 (1, 0, it2_);
  1025. }
  1026. BOOST_UBLAS_INLINE
  1027. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1028. typename self_type::
  1029. #endif
  1030. iterator1 end () const {
  1031. return (*this) ().find1 (1, (*this) ().size1 (), it2_);
  1032. }
  1033. BOOST_UBLAS_INLINE
  1034. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1035. typename self_type::
  1036. #endif
  1037. reverse_iterator1 rbegin () const {
  1038. return reverse_iterator1 (end ());
  1039. }
  1040. BOOST_UBLAS_INLINE
  1041. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1042. typename self_type::
  1043. #endif
  1044. reverse_iterator1 rend () const {
  1045. return reverse_iterator1 (begin ());
  1046. }
  1047. #endif
  1048. // Indices
  1049. BOOST_UBLAS_INLINE
  1050. size_type index1 () const {
  1051. return it1_;
  1052. }
  1053. BOOST_UBLAS_INLINE
  1054. size_type index2 () const {
  1055. return it2_;
  1056. }
  1057. // Assignment
  1058. BOOST_UBLAS_INLINE
  1059. iterator2 &operator = (const iterator2 &it) {
  1060. container_reference<self_type>::assign (&it ());
  1061. it1_ = it.it1_;
  1062. it2_ = it.it2_;
  1063. return *this;
  1064. }
  1065. // Comparison
  1066. BOOST_UBLAS_INLINE
  1067. bool operator == (const iterator2 &it) const {
  1068. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1069. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  1070. return it2_ == it.it2_;
  1071. }
  1072. BOOST_UBLAS_INLINE
  1073. bool operator < (const iterator2 &it) const {
  1074. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1075. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  1076. return it2_ < it.it2_;
  1077. }
  1078. private:
  1079. size_type it1_;
  1080. size_type it2_;
  1081. friend class const_iterator2;
  1082. };
  1083. #endif
  1084. BOOST_UBLAS_INLINE
  1085. iterator2 begin2 () {
  1086. return find2 (0, 0, 0);
  1087. }
  1088. BOOST_UBLAS_INLINE
  1089. iterator2 end2 () {
  1090. return find2 (0, 0, size_);
  1091. }
  1092. // Reverse iterators
  1093. BOOST_UBLAS_INLINE
  1094. const_reverse_iterator1 rbegin1 () const {
  1095. return const_reverse_iterator1 (end1 ());
  1096. }
  1097. BOOST_UBLAS_INLINE
  1098. const_reverse_iterator1 crbegin1 () const {
  1099. return rbegin1 ();
  1100. }
  1101. BOOST_UBLAS_INLINE
  1102. const_reverse_iterator1 rend1 () const {
  1103. return const_reverse_iterator1 (begin1 ());
  1104. }
  1105. BOOST_UBLAS_INLINE
  1106. const_reverse_iterator1 crend1 () const {
  1107. return rend1 ();
  1108. }
  1109. BOOST_UBLAS_INLINE
  1110. reverse_iterator1 rbegin1 () {
  1111. return reverse_iterator1 (end1 ());
  1112. }
  1113. BOOST_UBLAS_INLINE
  1114. reverse_iterator1 rend1 () {
  1115. return reverse_iterator1 (begin1 ());
  1116. }
  1117. BOOST_UBLAS_INLINE
  1118. const_reverse_iterator2 rbegin2 () const {
  1119. return const_reverse_iterator2 (end2 ());
  1120. }
  1121. BOOST_UBLAS_INLINE
  1122. const_reverse_iterator2 crbegin2 () const {
  1123. return rbegin2();
  1124. }
  1125. BOOST_UBLAS_INLINE
  1126. const_reverse_iterator2 rend2 () const {
  1127. return const_reverse_iterator2 (begin2 ());
  1128. }
  1129. BOOST_UBLAS_INLINE
  1130. const_reverse_iterator2 crend2 () const {
  1131. return rend2 ();
  1132. }
  1133. BOOST_UBLAS_INLINE
  1134. reverse_iterator2 rbegin2 () {
  1135. return reverse_iterator2 (end2 ());
  1136. }
  1137. BOOST_UBLAS_INLINE
  1138. reverse_iterator2 rend2 () {
  1139. return reverse_iterator2 (begin2 ());
  1140. }
  1141. private:
  1142. size_type size_;
  1143. array_type data_;
  1144. };
  1145. /** \brief A Hermitian matrix adaptator: convert a any matrix into a Hermitian matrix expression
  1146. *
  1147. * For a \f$(m\times n)\f$-dimensional matrix, the \c hermitian_adaptor will provide a hermitian matrix.
  1148. * Storage and location are based on those of the underlying matrix. This is important because
  1149. * a \c hermitian_adaptor does not copy the matrix data to a new place. Therefore, modifying values
  1150. * in a \c hermitian_adaptor matrix will also modify the underlying matrix too.
  1151. *
  1152. * \tparam M the type of matrix used to generate a hermitian matrix
  1153. */
  1154. template<class M, class TRI>
  1155. class hermitian_adaptor:
  1156. public matrix_expression<hermitian_adaptor<M, TRI> > {
  1157. typedef hermitian_adaptor<M, TRI> self_type;
  1158. typedef typename M::value_type &true_reference;
  1159. public:
  1160. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  1161. using matrix_expression<self_type>::operator ();
  1162. #endif
  1163. typedef const M const_matrix_type;
  1164. typedef M matrix_type;
  1165. typedef TRI triangular_type;
  1166. typedef typename M::size_type size_type;
  1167. typedef typename M::difference_type difference_type;
  1168. typedef typename M::value_type value_type;
  1169. typedef typename M::value_type const_reference;
  1170. #ifndef BOOST_UBLAS_STRICT_HERMITIAN
  1171. typedef typename boost::mpl::if_<boost::is_const<M>,
  1172. typename M::value_type,
  1173. typename M::reference>::type reference;
  1174. #else
  1175. typedef typename boost::mpl::if_<boost::is_const<M>,
  1176. typename M::value_type,
  1177. hermitian_matrix_element<self_type> >::type reference;
  1178. #endif
  1179. typedef typename boost::mpl::if_<boost::is_const<M>,
  1180. typename M::const_closure_type,
  1181. typename M::closure_type>::type matrix_closure_type;
  1182. typedef const self_type const_closure_type;
  1183. typedef self_type closure_type;
  1184. // Replaced by _temporary_traits to avoid type requirements on M
  1185. //typedef typename M::vector_temporary_type vector_temporary_type;
  1186. //typedef typename M::matrix_temporary_type matrix_temporary_type;
  1187. typedef typename storage_restrict_traits<typename M::storage_category,
  1188. packed_proxy_tag>::storage_category storage_category;
  1189. typedef typename M::orientation_category orientation_category;
  1190. // Construction and destruction
  1191. BOOST_UBLAS_INLINE
  1192. hermitian_adaptor (matrix_type &data):
  1193. matrix_expression<self_type> (),
  1194. data_ (data) {
  1195. BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
  1196. }
  1197. BOOST_UBLAS_INLINE
  1198. hermitian_adaptor (const hermitian_adaptor &m):
  1199. matrix_expression<self_type> (),
  1200. data_ (m.data_) {
  1201. BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
  1202. }
  1203. // Accessors
  1204. BOOST_UBLAS_INLINE
  1205. size_type size1 () const {
  1206. return data_.size1 ();
  1207. }
  1208. BOOST_UBLAS_INLINE
  1209. size_type size2 () const {
  1210. return data_.size2 ();
  1211. }
  1212. // Storage accessors
  1213. BOOST_UBLAS_INLINE
  1214. const matrix_closure_type &data () const {
  1215. return data_;
  1216. }
  1217. BOOST_UBLAS_INLINE
  1218. matrix_closure_type &data () {
  1219. return data_;
  1220. }
  1221. // Element access
  1222. #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
  1223. BOOST_UBLAS_INLINE
  1224. const_reference operator () (size_type i, size_type j) const {
  1225. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1226. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1227. // if (i == j)
  1228. // return type_traits<value_type>::real (data () (i, i));
  1229. // else
  1230. if (triangular_type::other (i, j))
  1231. return data () (i, j);
  1232. else
  1233. return type_traits<value_type>::conj (data () (j, i));
  1234. }
  1235. BOOST_UBLAS_INLINE
  1236. reference operator () (size_type i, size_type j) {
  1237. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1238. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1239. #ifndef BOOST_UBLAS_STRICT_HERMITIAN
  1240. if (triangular_type::other (i, j))
  1241. return data () (i, j);
  1242. else {
  1243. external_logic ().raise ();
  1244. return conj_ = type_traits<value_type>::conj (data () (j, i));
  1245. }
  1246. #else
  1247. if (triangular_type::other (i, j))
  1248. return reference (*this, i, j, data () (i, j));
  1249. else
  1250. return reference (*this, i, j, type_traits<value_type>::conj (data () (j, i)));
  1251. #endif
  1252. }
  1253. BOOST_UBLAS_INLINE
  1254. true_reference insert_element (size_type i, size_type j, value_type t) {
  1255. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1256. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1257. // if (i == j)
  1258. // data () (i, i) = type_traits<value_type>::real (t);
  1259. // else
  1260. if (triangular_type::other (i, j))
  1261. return data () (i, j) = t;
  1262. else
  1263. return data () (j, i) = type_traits<value_type>::conj (t);
  1264. }
  1265. #else
  1266. BOOST_UBLAS_INLINE
  1267. reference operator () (size_type i, size_type j) {
  1268. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1269. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1270. #ifndef BOOST_UBLAS_STRICT_HERMITIAN
  1271. if (triangular_type::other (i, j))
  1272. return data () (i, j);
  1273. else {
  1274. external_logic ().raise ();
  1275. return conj_ = type_traits<value_type>::conj (data () (j, i));
  1276. }
  1277. #else
  1278. if (triangular_type::other (i, j))
  1279. return reference (*this, i, j, data () (i, j));
  1280. else
  1281. return reference (*this, i, j, type_traits<value_type>::conj (data () (j, i)));
  1282. #endif
  1283. }
  1284. BOOST_UBLAS_INLINE
  1285. true_reference insert_element (size_type i, size_type j, value_type t) {
  1286. BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
  1287. BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
  1288. // if (i == j)
  1289. // data () (i, i) = type_traits<value_type>::real (t);
  1290. // else
  1291. if (triangular_type::other (i, j))
  1292. return data () (i, j) = t;
  1293. else
  1294. return data () (j, i) = type_traits<value_type>::conj (t);
  1295. }
  1296. #endif
  1297. // Assignment
  1298. BOOST_UBLAS_INLINE
  1299. hermitian_adaptor &operator = (const hermitian_adaptor &m) {
  1300. matrix_assign<scalar_assign, triangular_type> (*this, m);
  1301. return *this;
  1302. }
  1303. BOOST_UBLAS_INLINE
  1304. hermitian_adaptor &assign_temporary (hermitian_adaptor &m) {
  1305. *this = m;
  1306. return *this;
  1307. }
  1308. template<class AE>
  1309. BOOST_UBLAS_INLINE
  1310. hermitian_adaptor &operator = (const matrix_expression<AE> &ae) {
  1311. matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae));
  1312. return *this;
  1313. }
  1314. template<class AE>
  1315. BOOST_UBLAS_INLINE
  1316. hermitian_adaptor &assign (const matrix_expression<AE> &ae) {
  1317. matrix_assign<scalar_assign, triangular_type> (*this, ae);
  1318. return *this;
  1319. }
  1320. template<class AE>
  1321. BOOST_UBLAS_INLINE
  1322. hermitian_adaptor& operator += (const matrix_expression<AE> &ae) {
  1323. matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae));
  1324. return *this;
  1325. }
  1326. template<class AE>
  1327. BOOST_UBLAS_INLINE
  1328. hermitian_adaptor &plus_assign (const matrix_expression<AE> &ae) {
  1329. matrix_assign<scalar_plus_assign, triangular_type> (*this, ae);
  1330. return *this;
  1331. }
  1332. template<class AE>
  1333. BOOST_UBLAS_INLINE
  1334. hermitian_adaptor& operator -= (const matrix_expression<AE> &ae) {
  1335. matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae));
  1336. return *this;
  1337. }
  1338. template<class AE>
  1339. BOOST_UBLAS_INLINE
  1340. hermitian_adaptor &minus_assign (const matrix_expression<AE> &ae) {
  1341. matrix_assign<scalar_minus_assign, triangular_type> (*this, ae);
  1342. return *this;
  1343. }
  1344. template<class AT>
  1345. BOOST_UBLAS_INLINE
  1346. hermitian_adaptor& operator *= (const AT &at) {
  1347. // Multiplication is only allowed for real scalars,
  1348. // otherwise the resulting matrix isn't hermitian.
  1349. // Thanks to Peter Schmitteckert for spotting this.
  1350. BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
  1351. matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  1352. return *this;
  1353. }
  1354. template<class AT>
  1355. BOOST_UBLAS_INLINE
  1356. hermitian_adaptor& operator /= (const AT &at) {
  1357. // Multiplication is only allowed for real scalars,
  1358. // otherwise the resulting matrix isn't hermitian.
  1359. // Thanks to Peter Schmitteckert for spotting this.
  1360. BOOST_UBLAS_CHECK (type_traits<value_type>::imag (at) == 0, non_real ());
  1361. matrix_assign_scalar<scalar_divides_assign> (*this, at);
  1362. return *this;
  1363. }
  1364. // Closure comparison
  1365. BOOST_UBLAS_INLINE
  1366. bool same_closure (const hermitian_adaptor &ha) const {
  1367. return (*this).data ().same_closure (ha.data ());
  1368. }
  1369. // Swapping
  1370. BOOST_UBLAS_INLINE
  1371. void swap (hermitian_adaptor &m) {
  1372. if (this != &m)
  1373. matrix_swap<scalar_swap, triangular_type> (*this, m);
  1374. }
  1375. BOOST_UBLAS_INLINE
  1376. friend void swap (hermitian_adaptor &m1, hermitian_adaptor &m2) {
  1377. m1.swap (m2);
  1378. }
  1379. // Iterator types
  1380. private:
  1381. // Use matrix iterator
  1382. typedef typename M::const_iterator1 const_subiterator1_type;
  1383. typedef typename boost::mpl::if_<boost::is_const<M>,
  1384. typename M::const_iterator1,
  1385. typename M::iterator1>::type subiterator1_type;
  1386. typedef typename M::const_iterator2 const_subiterator2_type;
  1387. typedef typename boost::mpl::if_<boost::is_const<M>,
  1388. typename M::const_iterator2,
  1389. typename M::iterator2>::type subiterator2_type;
  1390. public:
  1391. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1392. typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
  1393. typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
  1394. typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
  1395. typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
  1396. #else
  1397. class const_iterator1;
  1398. class iterator1;
  1399. class const_iterator2;
  1400. class iterator2;
  1401. #endif
  1402. typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  1403. typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  1404. typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  1405. typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  1406. // Element lookup
  1407. BOOST_UBLAS_INLINE
  1408. const_iterator1 find1 (int rank, size_type i, size_type j) const {
  1409. if (triangular_type::other (i, j)) {
  1410. if (triangular_type::other (size1 (), j)) {
  1411. return const_iterator1 (*this, 0, 0,
  1412. data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j),
  1413. data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ()));
  1414. } else {
  1415. return const_iterator1 (*this, 0, 1,
  1416. data ().find1 (rank, i, j), data ().find1 (rank, j, j),
  1417. data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ()));
  1418. }
  1419. } else {
  1420. if (triangular_type::other (size1 (), j)) {
  1421. return const_iterator1 (*this, 1, 0,
  1422. data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j),
  1423. data ().find2 (rank, j, i), data ().find2 (rank, j, j));
  1424. } else {
  1425. return const_iterator1 (*this, 1, 1,
  1426. data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()),
  1427. data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ()));
  1428. }
  1429. }
  1430. }
  1431. BOOST_UBLAS_INLINE
  1432. iterator1 find1 (int rank, size_type i, size_type j) {
  1433. if (rank == 1)
  1434. i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
  1435. if (rank == 0)
  1436. i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
  1437. return iterator1 (*this, data ().find1 (rank, i, j));
  1438. }
  1439. BOOST_UBLAS_INLINE
  1440. const_iterator2 find2 (int rank, size_type i, size_type j) const {
  1441. if (triangular_type::other (i, j)) {
  1442. if (triangular_type::other (i, size2 ())) {
  1443. return const_iterator2 (*this, 1, 1,
  1444. data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()),
  1445. data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ()));
  1446. } else {
  1447. return const_iterator2 (*this, 1, 0,
  1448. data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i),
  1449. data ().find2 (rank, i, j), data ().find2 (rank, i, i));
  1450. }
  1451. } else {
  1452. if (triangular_type::other (i, size2 ())) {
  1453. return const_iterator2 (*this, 0, 1,
  1454. data ().find1 (rank, j, i), data ().find1 (rank, i, i),
  1455. data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ()));
  1456. } else {
  1457. return const_iterator2 (*this, 0, 0,
  1458. data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i),
  1459. data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ()));
  1460. }
  1461. }
  1462. }
  1463. BOOST_UBLAS_INLINE
  1464. iterator2 find2 (int rank, size_type i, size_type j) {
  1465. if (rank == 1)
  1466. j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
  1467. if (rank == 0)
  1468. j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
  1469. return iterator2 (*this, data ().find2 (rank, i, j));
  1470. }
  1471. // Iterators simply are indices.
  1472. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1473. class const_iterator1:
  1474. public container_const_reference<hermitian_adaptor>,
  1475. public random_access_iterator_base<typename iterator_restrict_traits<
  1476. typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
  1477. const_iterator1, value_type> {
  1478. public:
  1479. typedef typename const_subiterator1_type::value_type value_type;
  1480. typedef typename const_subiterator1_type::difference_type difference_type;
  1481. // FIXME no better way to not return the address of a temporary?
  1482. // typedef typename const_subiterator1_type::reference reference;
  1483. typedef typename const_subiterator1_type::value_type reference;
  1484. typedef typename const_subiterator1_type::pointer pointer;
  1485. typedef const_iterator2 dual_iterator_type;
  1486. typedef const_reverse_iterator2 dual_reverse_iterator_type;
  1487. // Construction and destruction
  1488. BOOST_UBLAS_INLINE
  1489. const_iterator1 ():
  1490. container_const_reference<self_type> (),
  1491. begin_ (-1), end_ (-1), current_ (-1),
  1492. it1_begin_ (), it1_end_ (), it1_ (),
  1493. it2_begin_ (), it2_end_ (), it2_ () {}
  1494. BOOST_UBLAS_INLINE
  1495. const_iterator1 (const self_type &m, int begin, int end,
  1496. const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
  1497. const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
  1498. container_const_reference<self_type> (m),
  1499. begin_ (begin), end_ (end), current_ (begin),
  1500. it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
  1501. it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
  1502. if (current_ == 0 && it1_ == it1_end_)
  1503. current_ = 1;
  1504. if (current_ == 1 && it2_ == it2_end_)
  1505. current_ = 0;
  1506. if ((current_ == 0 && it1_ == it1_end_) ||
  1507. (current_ == 1 && it2_ == it2_end_))
  1508. current_ = end_;
  1509. BOOST_UBLAS_CHECK (current_ == end_ ||
  1510. (current_ == 0 && it1_ != it1_end_) ||
  1511. (current_ == 1 && it2_ != it2_end_), internal_logic ());
  1512. }
  1513. // FIXME cannot compile
  1514. // iterator1 does not have these members!
  1515. BOOST_UBLAS_INLINE
  1516. const_iterator1 (const iterator1 &it):
  1517. container_const_reference<self_type> (it ()),
  1518. begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
  1519. it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
  1520. it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
  1521. BOOST_UBLAS_CHECK (current_ == end_ ||
  1522. (current_ == 0 && it1_ != it1_end_) ||
  1523. (current_ == 1 && it2_ != it2_end_), internal_logic ());
  1524. }
  1525. // Arithmetic
  1526. BOOST_UBLAS_INLINE
  1527. const_iterator1 &operator ++ () {
  1528. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1529. if (current_ == 0) {
  1530. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  1531. ++ it1_;
  1532. if (it1_ == it1_end_ && end_ == 1) {
  1533. it2_ = it2_begin_;
  1534. current_ = 1;
  1535. }
  1536. } else /* if (current_ == 1) */ {
  1537. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  1538. ++ it2_;
  1539. if (it2_ == it2_end_ && end_ == 0) {
  1540. it1_ = it1_begin_;
  1541. current_ = 0;
  1542. }
  1543. }
  1544. return *this;
  1545. }
  1546. BOOST_UBLAS_INLINE
  1547. const_iterator1 &operator -- () {
  1548. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1549. if (current_ == 0) {
  1550. if (it1_ == it1_begin_ && begin_ == 1) {
  1551. it2_ = it2_end_;
  1552. BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
  1553. -- it2_;
  1554. current_ = 1;
  1555. } else {
  1556. -- it1_;
  1557. }
  1558. } else /* if (current_ == 1) */ {
  1559. if (it2_ == it2_begin_ && begin_ == 0) {
  1560. it1_ = it1_end_;
  1561. BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
  1562. -- it1_;
  1563. current_ = 0;
  1564. } else {
  1565. -- it2_;
  1566. }
  1567. }
  1568. return *this;
  1569. }
  1570. BOOST_UBLAS_INLINE
  1571. const_iterator1 &operator += (difference_type n) {
  1572. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1573. if (current_ == 0) {
  1574. size_type d = (std::min) (n, it1_end_ - it1_);
  1575. it1_ += d;
  1576. n -= d;
  1577. if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
  1578. BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
  1579. d = (std::min) (n, it2_end_ - it2_begin_);
  1580. it2_ = it2_begin_ + d;
  1581. n -= d;
  1582. current_ = 1;
  1583. }
  1584. } else /* if (current_ == 1) */ {
  1585. size_type d = (std::min) (n, it2_end_ - it2_);
  1586. it2_ += d;
  1587. n -= d;
  1588. if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
  1589. BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
  1590. d = (std::min) (n, it1_end_ - it1_begin_);
  1591. it1_ = it1_begin_ + d;
  1592. n -= d;
  1593. current_ = 0;
  1594. }
  1595. }
  1596. BOOST_UBLAS_CHECK (n == 0, external_logic ());
  1597. return *this;
  1598. }
  1599. BOOST_UBLAS_INLINE
  1600. const_iterator1 &operator -= (difference_type n) {
  1601. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1602. if (current_ == 0) {
  1603. size_type d = (std::min) (n, it1_ - it1_begin_);
  1604. it1_ -= d;
  1605. n -= d;
  1606. if (n > 0) {
  1607. BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
  1608. d = (std::min) (n, it2_end_ - it2_begin_);
  1609. it2_ = it2_end_ - d;
  1610. n -= d;
  1611. current_ = 1;
  1612. }
  1613. } else /* if (current_ == 1) */ {
  1614. size_type d = (std::min) (n, it2_ - it2_begin_);
  1615. it2_ -= d;
  1616. n -= d;
  1617. if (n > 0) {
  1618. BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
  1619. d = (std::min) (n, it1_end_ - it1_begin_);
  1620. it1_ = it1_end_ - d;
  1621. n -= d;
  1622. current_ = 0;
  1623. }
  1624. }
  1625. BOOST_UBLAS_CHECK (n == 0, external_logic ());
  1626. return *this;
  1627. }
  1628. BOOST_UBLAS_INLINE
  1629. difference_type operator - (const const_iterator1 &it) const {
  1630. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1631. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1632. BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
  1633. BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
  1634. if (current_ == 0 && it.current_ == 0) {
  1635. return it1_ - it.it1_;
  1636. } else if (current_ == 0 && it.current_ == 1) {
  1637. if (end_ == 1 && it.end_ == 1) {
  1638. return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
  1639. } else /* if (end_ == 0 && it.end_ == 0) */ {
  1640. return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
  1641. }
  1642. } else if (current_ == 1 && it.current_ == 0) {
  1643. if (end_ == 1 && it.end_ == 1) {
  1644. return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
  1645. } else /* if (end_ == 0 && it.end_ == 0) */ {
  1646. return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
  1647. }
  1648. } else /* if (current_ == 1 && it.current_ == 1) */ {
  1649. return it2_ - it.it2_;
  1650. }
  1651. }
  1652. // Dereference
  1653. BOOST_UBLAS_INLINE
  1654. const_reference operator * () const {
  1655. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1656. if (current_ == 0) {
  1657. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  1658. if (triangular_type::other (index1 (), index2 ()))
  1659. return *it1_;
  1660. else
  1661. return type_traits<value_type>::conj (*it1_);
  1662. } else /* if (current_ == 1) */ {
  1663. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  1664. if (triangular_type::other (index1 (), index2 ()))
  1665. return *it2_;
  1666. else
  1667. return type_traits<value_type>::conj (*it2_);
  1668. }
  1669. }
  1670. BOOST_UBLAS_INLINE
  1671. const_reference operator [] (difference_type n) const {
  1672. return *(*this + n);
  1673. }
  1674. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1675. BOOST_UBLAS_INLINE
  1676. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1677. typename self_type::
  1678. #endif
  1679. const_iterator2 begin () const {
  1680. return (*this) ().find2 (1, index1 (), 0);
  1681. }
  1682. BOOST_UBLAS_INLINE
  1683. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1684. typename self_type::
  1685. #endif
  1686. const_iterator2 cbegin () const {
  1687. return begin ();
  1688. }
  1689. BOOST_UBLAS_INLINE
  1690. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1691. typename self_type::
  1692. #endif
  1693. const_iterator2 end () const {
  1694. return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
  1695. }
  1696. BOOST_UBLAS_INLINE
  1697. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1698. typename self_type::
  1699. #endif
  1700. const_iterator2 cend () const {
  1701. return end ();
  1702. }
  1703. BOOST_UBLAS_INLINE
  1704. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1705. typename self_type::
  1706. #endif
  1707. const_reverse_iterator2 rbegin () const {
  1708. return const_reverse_iterator2 (end ());
  1709. }
  1710. BOOST_UBLAS_INLINE
  1711. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1712. typename self_type::
  1713. #endif
  1714. const_reverse_iterator2 crbegin () const {
  1715. return rbegin ();
  1716. }
  1717. BOOST_UBLAS_INLINE
  1718. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1719. typename self_type::
  1720. #endif
  1721. const_reverse_iterator2 rend () const {
  1722. return const_reverse_iterator2 (begin ());
  1723. }
  1724. BOOST_UBLAS_INLINE
  1725. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1726. typename self_type::
  1727. #endif
  1728. const_reverse_iterator2 crend () const {
  1729. return rend ();
  1730. }
  1731. #endif
  1732. // Indices
  1733. BOOST_UBLAS_INLINE
  1734. size_type index1 () const {
  1735. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1736. if (current_ == 0) {
  1737. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  1738. return it1_.index1 ();
  1739. } else /* if (current_ == 1) */ {
  1740. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  1741. return it2_.index2 ();
  1742. }
  1743. }
  1744. BOOST_UBLAS_INLINE
  1745. size_type index2 () const {
  1746. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1747. if (current_ == 0) {
  1748. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  1749. return it1_.index2 ();
  1750. } else /* if (current_ == 1) */ {
  1751. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  1752. return it2_.index1 ();
  1753. }
  1754. }
  1755. // Assignment
  1756. BOOST_UBLAS_INLINE
  1757. const_iterator1 &operator = (const const_iterator1 &it) {
  1758. container_const_reference<self_type>::assign (&it ());
  1759. begin_ = it.begin_;
  1760. end_ = it.end_;
  1761. current_ = it.current_;
  1762. it1_begin_ = it.it1_begin_;
  1763. it1_end_ = it.it1_end_;
  1764. it1_ = it.it1_;
  1765. it2_begin_ = it.it2_begin_;
  1766. it2_end_ = it.it2_end_;
  1767. it2_ = it.it2_;
  1768. return *this;
  1769. }
  1770. // Comparison
  1771. BOOST_UBLAS_INLINE
  1772. bool operator == (const const_iterator1 &it) const {
  1773. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1774. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1775. BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
  1776. BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
  1777. return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
  1778. (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
  1779. }
  1780. BOOST_UBLAS_INLINE
  1781. bool operator < (const const_iterator1 &it) const {
  1782. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1783. return it - *this > 0;
  1784. }
  1785. private:
  1786. int begin_;
  1787. int end_;
  1788. int current_;
  1789. const_subiterator1_type it1_begin_;
  1790. const_subiterator1_type it1_end_;
  1791. const_subiterator1_type it1_;
  1792. const_subiterator2_type it2_begin_;
  1793. const_subiterator2_type it2_end_;
  1794. const_subiterator2_type it2_;
  1795. };
  1796. #endif
  1797. BOOST_UBLAS_INLINE
  1798. const_iterator1 begin1 () const {
  1799. return find1 (0, 0, 0);
  1800. }
  1801. BOOST_UBLAS_INLINE
  1802. const_iterator1 cbegin1 () const {
  1803. return begin1 ();
  1804. }
  1805. BOOST_UBLAS_INLINE
  1806. const_iterator1 end1 () const {
  1807. return find1 (0, size1 (), 0);
  1808. }
  1809. BOOST_UBLAS_INLINE
  1810. const_iterator1 cend1 () const {
  1811. return end1 ();
  1812. }
  1813. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1814. class iterator1:
  1815. public container_reference<hermitian_adaptor>,
  1816. public random_access_iterator_base<typename iterator_restrict_traits<
  1817. typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  1818. iterator1, value_type> {
  1819. public:
  1820. typedef typename subiterator1_type::value_type value_type;
  1821. typedef typename subiterator1_type::difference_type difference_type;
  1822. typedef typename subiterator1_type::reference reference;
  1823. typedef typename subiterator1_type::pointer pointer;
  1824. typedef iterator2 dual_iterator_type;
  1825. typedef reverse_iterator2 dual_reverse_iterator_type;
  1826. // Construction and destruction
  1827. BOOST_UBLAS_INLINE
  1828. iterator1 ():
  1829. container_reference<self_type> (), it1_ () {}
  1830. BOOST_UBLAS_INLINE
  1831. iterator1 (self_type &m, const subiterator1_type &it1):
  1832. container_reference<self_type> (m), it1_ (it1) {}
  1833. // Arithmetic
  1834. BOOST_UBLAS_INLINE
  1835. iterator1 &operator ++ () {
  1836. ++ it1_;
  1837. return *this;
  1838. }
  1839. BOOST_UBLAS_INLINE
  1840. iterator1 &operator -- () {
  1841. -- it1_;
  1842. return *this;
  1843. }
  1844. BOOST_UBLAS_INLINE
  1845. iterator1 &operator += (difference_type n) {
  1846. it1_ += n;
  1847. return *this;
  1848. }
  1849. BOOST_UBLAS_INLINE
  1850. iterator1 &operator -= (difference_type n) {
  1851. it1_ -= n;
  1852. return *this;
  1853. }
  1854. BOOST_UBLAS_INLINE
  1855. difference_type operator - (const iterator1 &it) const {
  1856. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1857. return it1_ - it.it1_;
  1858. }
  1859. // Dereference
  1860. BOOST_UBLAS_INLINE
  1861. reference operator * () const {
  1862. return *it1_;
  1863. }
  1864. BOOST_UBLAS_INLINE
  1865. reference operator [] (difference_type n) const {
  1866. return *(*this + n);
  1867. }
  1868. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1869. BOOST_UBLAS_INLINE
  1870. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1871. typename self_type::
  1872. #endif
  1873. iterator2 begin () const {
  1874. return (*this) ().find2 (1, index1 (), 0);
  1875. }
  1876. BOOST_UBLAS_INLINE
  1877. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1878. typename self_type::
  1879. #endif
  1880. iterator2 end () const {
  1881. return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
  1882. }
  1883. BOOST_UBLAS_INLINE
  1884. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1885. typename self_type::
  1886. #endif
  1887. reverse_iterator2 rbegin () const {
  1888. return reverse_iterator2 (end ());
  1889. }
  1890. BOOST_UBLAS_INLINE
  1891. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1892. typename self_type::
  1893. #endif
  1894. reverse_iterator2 rend () const {
  1895. return reverse_iterator2 (begin ());
  1896. }
  1897. #endif
  1898. // Indices
  1899. BOOST_UBLAS_INLINE
  1900. size_type index1 () const {
  1901. return it1_.index1 ();
  1902. }
  1903. BOOST_UBLAS_INLINE
  1904. size_type index2 () const {
  1905. return it1_.index2 ();
  1906. }
  1907. // Assignment
  1908. BOOST_UBLAS_INLINE
  1909. iterator1 &operator = (const iterator1 &it) {
  1910. container_reference<self_type>::assign (&it ());
  1911. it1_ = it.it1_;
  1912. return *this;
  1913. }
  1914. // Comparison
  1915. BOOST_UBLAS_INLINE
  1916. bool operator == (const iterator1 &it) const {
  1917. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1918. return it1_ == it.it1_;
  1919. }
  1920. BOOST_UBLAS_INLINE
  1921. bool operator < (const iterator1 &it) const {
  1922. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1923. return it1_ < it.it1_;
  1924. }
  1925. private:
  1926. subiterator1_type it1_;
  1927. friend class const_iterator1;
  1928. };
  1929. #endif
  1930. BOOST_UBLAS_INLINE
  1931. iterator1 begin1 () {
  1932. return find1 (0, 0, 0);
  1933. }
  1934. BOOST_UBLAS_INLINE
  1935. iterator1 end1 () {
  1936. return find1 (0, size1 (), 0);
  1937. }
  1938. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1939. class const_iterator2:
  1940. public container_const_reference<hermitian_adaptor>,
  1941. public random_access_iterator_base<typename iterator_restrict_traits<
  1942. typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
  1943. const_iterator2, value_type> {
  1944. public:
  1945. typedef typename const_subiterator2_type::value_type value_type;
  1946. typedef typename const_subiterator2_type::difference_type difference_type;
  1947. // FIXME no better way to not return the address of a temporary?
  1948. // typedef typename const_subiterator2_type::reference reference;
  1949. typedef typename const_subiterator2_type::value_type reference;
  1950. typedef typename const_subiterator2_type::pointer pointer;
  1951. typedef const_iterator1 dual_iterator_type;
  1952. typedef const_reverse_iterator1 dual_reverse_iterator_type;
  1953. // Construction and destruction
  1954. BOOST_UBLAS_INLINE
  1955. const_iterator2 ():
  1956. container_const_reference<self_type> (),
  1957. begin_ (-1), end_ (-1), current_ (-1),
  1958. it1_begin_ (), it1_end_ (), it1_ (),
  1959. it2_begin_ (), it2_end_ (), it2_ () {}
  1960. BOOST_UBLAS_INLINE
  1961. const_iterator2 (const self_type &m, int begin, int end,
  1962. const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
  1963. const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
  1964. container_const_reference<self_type> (m),
  1965. begin_ (begin), end_ (end), current_ (begin),
  1966. it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
  1967. it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
  1968. if (current_ == 0 && it1_ == it1_end_)
  1969. current_ = 1;
  1970. if (current_ == 1 && it2_ == it2_end_)
  1971. current_ = 0;
  1972. if ((current_ == 0 && it1_ == it1_end_) ||
  1973. (current_ == 1 && it2_ == it2_end_))
  1974. current_ = end_;
  1975. BOOST_UBLAS_CHECK (current_ == end_ ||
  1976. (current_ == 0 && it1_ != it1_end_) ||
  1977. (current_ == 1 && it2_ != it2_end_), internal_logic ());
  1978. }
  1979. // FIXME cannot compiler
  1980. // iterator2 does not have these members!
  1981. BOOST_UBLAS_INLINE
  1982. const_iterator2 (const iterator2 &it):
  1983. container_const_reference<self_type> (it ()),
  1984. begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
  1985. it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
  1986. it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
  1987. BOOST_UBLAS_CHECK (current_ == end_ ||
  1988. (current_ == 0 && it1_ != it1_end_) ||
  1989. (current_ == 1 && it2_ != it2_end_), internal_logic ());
  1990. }
  1991. // Arithmetic
  1992. BOOST_UBLAS_INLINE
  1993. const_iterator2 &operator ++ () {
  1994. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  1995. if (current_ == 0) {
  1996. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  1997. ++ it1_;
  1998. if (it1_ == it1_end_ && end_ == 1) {
  1999. it2_ = it2_begin_;
  2000. current_ = 1;
  2001. }
  2002. } else /* if (current_ == 1) */ {
  2003. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  2004. ++ it2_;
  2005. if (it2_ == it2_end_ && end_ == 0) {
  2006. it1_ = it1_begin_;
  2007. current_ = 0;
  2008. }
  2009. }
  2010. return *this;
  2011. }
  2012. BOOST_UBLAS_INLINE
  2013. const_iterator2 &operator -- () {
  2014. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  2015. if (current_ == 0) {
  2016. if (it1_ == it1_begin_ && begin_ == 1) {
  2017. it2_ = it2_end_;
  2018. BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
  2019. -- it2_;
  2020. current_ = 1;
  2021. } else {
  2022. -- it1_;
  2023. }
  2024. } else /* if (current_ == 1) */ {
  2025. if (it2_ == it2_begin_ && begin_ == 0) {
  2026. it1_ = it1_end_;
  2027. BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
  2028. -- it1_;
  2029. current_ = 0;
  2030. } else {
  2031. -- it2_;
  2032. }
  2033. }
  2034. return *this;
  2035. }
  2036. BOOST_UBLAS_INLINE
  2037. const_iterator2 &operator += (difference_type n) {
  2038. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  2039. if (current_ == 0) {
  2040. size_type d = (std::min) (n, it1_end_ - it1_);
  2041. it1_ += d;
  2042. n -= d;
  2043. if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
  2044. BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
  2045. d = (std::min) (n, it2_end_ - it2_begin_);
  2046. it2_ = it2_begin_ + d;
  2047. n -= d;
  2048. current_ = 1;
  2049. }
  2050. } else /* if (current_ == 1) */ {
  2051. size_type d = (std::min) (n, it2_end_ - it2_);
  2052. it2_ += d;
  2053. n -= d;
  2054. if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
  2055. BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
  2056. d = (std::min) (n, it1_end_ - it1_begin_);
  2057. it1_ = it1_begin_ + d;
  2058. n -= d;
  2059. current_ = 0;
  2060. }
  2061. }
  2062. BOOST_UBLAS_CHECK (n == 0, external_logic ());
  2063. return *this;
  2064. }
  2065. BOOST_UBLAS_INLINE
  2066. const_iterator2 &operator -= (difference_type n) {
  2067. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  2068. if (current_ == 0) {
  2069. size_type d = (std::min) (n, it1_ - it1_begin_);
  2070. it1_ -= d;
  2071. n -= d;
  2072. if (n > 0) {
  2073. BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
  2074. d = (std::min) (n, it2_end_ - it2_begin_);
  2075. it2_ = it2_end_ - d;
  2076. n -= d;
  2077. current_ = 1;
  2078. }
  2079. } else /* if (current_ == 1) */ {
  2080. size_type d = (std::min) (n, it2_ - it2_begin_);
  2081. it2_ -= d;
  2082. n -= d;
  2083. if (n > 0) {
  2084. BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
  2085. d = (std::min) (n, it1_end_ - it1_begin_);
  2086. it1_ = it1_end_ - d;
  2087. n -= d;
  2088. current_ = 0;
  2089. }
  2090. }
  2091. BOOST_UBLAS_CHECK (n == 0, external_logic ());
  2092. return *this;
  2093. }
  2094. BOOST_UBLAS_INLINE
  2095. difference_type operator - (const const_iterator2 &it) const {
  2096. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2097. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  2098. BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
  2099. BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
  2100. if (current_ == 0 && it.current_ == 0) {
  2101. return it1_ - it.it1_;
  2102. } else if (current_ == 0 && it.current_ == 1) {
  2103. if (end_ == 1 && it.end_ == 1) {
  2104. return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
  2105. } else /* if (end_ == 0 && it.end_ == 0) */ {
  2106. return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
  2107. }
  2108. } else if (current_ == 1 && it.current_ == 0) {
  2109. if (end_ == 1 && it.end_ == 1) {
  2110. return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
  2111. } else /* if (end_ == 0 && it.end_ == 0) */ {
  2112. return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
  2113. }
  2114. } else /* if (current_ == 1 && it.current_ == 1) */ {
  2115. return it2_ - it.it2_;
  2116. }
  2117. }
  2118. // Dereference
  2119. BOOST_UBLAS_INLINE
  2120. const_reference operator * () const {
  2121. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  2122. if (current_ == 0) {
  2123. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  2124. if (triangular_type::other (index1 (), index2 ()))
  2125. return *it1_;
  2126. else
  2127. return type_traits<value_type>::conj (*it1_);
  2128. } else /* if (current_ == 1) */ {
  2129. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  2130. if (triangular_type::other (index1 (), index2 ()))
  2131. return *it2_;
  2132. else
  2133. return type_traits<value_type>::conj (*it2_);
  2134. }
  2135. }
  2136. BOOST_UBLAS_INLINE
  2137. const_reference operator [] (difference_type n) const {
  2138. return *(*this + n);
  2139. }
  2140. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  2141. BOOST_UBLAS_INLINE
  2142. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2143. typename self_type::
  2144. #endif
  2145. const_iterator1 begin () const {
  2146. return (*this) ().find1 (1, 0, index2 ());
  2147. }
  2148. BOOST_UBLAS_INLINE
  2149. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2150. typename self_type::
  2151. #endif
  2152. const_iterator1 cbegin () const {
  2153. return begin ();
  2154. }
  2155. BOOST_UBLAS_INLINE
  2156. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2157. typename self_type::
  2158. #endif
  2159. const_iterator1 end () const {
  2160. return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
  2161. }
  2162. BOOST_UBLAS_INLINE
  2163. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2164. typename self_type::
  2165. #endif
  2166. const_iterator1 cend () const {
  2167. return end ();
  2168. }
  2169. BOOST_UBLAS_INLINE
  2170. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2171. typename self_type::
  2172. #endif
  2173. const_reverse_iterator1 rbegin () const {
  2174. return const_reverse_iterator1 (end ());
  2175. }
  2176. BOOST_UBLAS_INLINE
  2177. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2178. typename self_type::
  2179. #endif
  2180. const_reverse_iterator1 crbegin () const {
  2181. return rbegin ();
  2182. }
  2183. BOOST_UBLAS_INLINE
  2184. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2185. typename self_type::
  2186. #endif
  2187. const_reverse_iterator1 rend () const {
  2188. return const_reverse_iterator1 (begin ());
  2189. }
  2190. BOOST_UBLAS_INLINE
  2191. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2192. typename self_type::
  2193. #endif
  2194. const_reverse_iterator1 crend () const {
  2195. return end ();
  2196. }
  2197. #endif
  2198. // Indices
  2199. BOOST_UBLAS_INLINE
  2200. size_type index1 () const {
  2201. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  2202. if (current_ == 0) {
  2203. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  2204. return it1_.index2 ();
  2205. } else /* if (current_ == 1) */ {
  2206. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  2207. return it2_.index1 ();
  2208. }
  2209. }
  2210. BOOST_UBLAS_INLINE
  2211. size_type index2 () const {
  2212. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  2213. if (current_ == 0) {
  2214. BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
  2215. return it1_.index1 ();
  2216. } else /* if (current_ == 1) */ {
  2217. BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
  2218. return it2_.index2 ();
  2219. }
  2220. }
  2221. // Assignment
  2222. BOOST_UBLAS_INLINE
  2223. const_iterator2 &operator = (const const_iterator2 &it) {
  2224. container_const_reference<self_type>::assign (&it ());
  2225. begin_ = it.begin_;
  2226. end_ = it.end_;
  2227. current_ = it.current_;
  2228. it1_begin_ = it.it1_begin_;
  2229. it1_end_ = it.it1_end_;
  2230. it1_ = it.it1_;
  2231. it2_begin_ = it.it2_begin_;
  2232. it2_end_ = it.it2_end_;
  2233. it2_ = it.it2_;
  2234. return *this;
  2235. }
  2236. // Comparison
  2237. BOOST_UBLAS_INLINE
  2238. bool operator == (const const_iterator2 &it) const {
  2239. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2240. BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
  2241. BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
  2242. BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
  2243. return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
  2244. (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
  2245. }
  2246. BOOST_UBLAS_INLINE
  2247. bool operator < (const const_iterator2 &it) const {
  2248. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2249. return it - *this > 0;
  2250. }
  2251. private:
  2252. int begin_;
  2253. int end_;
  2254. int current_;
  2255. const_subiterator1_type it1_begin_;
  2256. const_subiterator1_type it1_end_;
  2257. const_subiterator1_type it1_;
  2258. const_subiterator2_type it2_begin_;
  2259. const_subiterator2_type it2_end_;
  2260. const_subiterator2_type it2_;
  2261. };
  2262. #endif
  2263. BOOST_UBLAS_INLINE
  2264. const_iterator2 begin2 () const {
  2265. return find2 (0, 0, 0);
  2266. }
  2267. BOOST_UBLAS_INLINE
  2268. const_iterator2 cbegin2 () const {
  2269. return begin2 ();
  2270. }
  2271. BOOST_UBLAS_INLINE
  2272. const_iterator2 end2 () const {
  2273. return find2 (0, 0, size2 ());
  2274. }
  2275. BOOST_UBLAS_INLINE
  2276. const_iterator2 cend2 () const {
  2277. return end2 ();
  2278. }
  2279. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  2280. class iterator2:
  2281. public container_reference<hermitian_adaptor>,
  2282. public random_access_iterator_base<typename iterator_restrict_traits<
  2283. typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
  2284. iterator2, value_type> {
  2285. public:
  2286. typedef typename subiterator2_type::value_type value_type;
  2287. typedef typename subiterator2_type::difference_type difference_type;
  2288. typedef typename subiterator2_type::reference reference;
  2289. typedef typename subiterator2_type::pointer pointer;
  2290. typedef iterator1 dual_iterator_type;
  2291. typedef reverse_iterator1 dual_reverse_iterator_type;
  2292. // Construction and destruction
  2293. BOOST_UBLAS_INLINE
  2294. iterator2 ():
  2295. container_reference<self_type> (), it2_ () {}
  2296. BOOST_UBLAS_INLINE
  2297. iterator2 (self_type &m, const subiterator2_type &it2):
  2298. container_reference<self_type> (m), it2_ (it2) {}
  2299. // Arithmetic
  2300. BOOST_UBLAS_INLINE
  2301. iterator2 &operator ++ () {
  2302. ++ it2_;
  2303. return *this;
  2304. }
  2305. BOOST_UBLAS_INLINE
  2306. iterator2 &operator -- () {
  2307. -- it2_;
  2308. return *this;
  2309. }
  2310. BOOST_UBLAS_INLINE
  2311. iterator2 &operator += (difference_type n) {
  2312. it2_ += n;
  2313. return *this;
  2314. }
  2315. BOOST_UBLAS_INLINE
  2316. iterator2 &operator -= (difference_type n) {
  2317. it2_ -= n;
  2318. return *this;
  2319. }
  2320. BOOST_UBLAS_INLINE
  2321. difference_type operator - (const iterator2 &it) const {
  2322. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2323. return it2_ - it.it2_;
  2324. }
  2325. // Dereference
  2326. BOOST_UBLAS_INLINE
  2327. reference operator * () const {
  2328. return *it2_;
  2329. }
  2330. BOOST_UBLAS_INLINE
  2331. reference operator [] (difference_type n) const {
  2332. return *(*this + n);
  2333. }
  2334. #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  2335. BOOST_UBLAS_INLINE
  2336. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2337. typename self_type::
  2338. #endif
  2339. iterator1 begin () const {
  2340. return (*this) ().find1 (1, 0, index2 ());
  2341. }
  2342. BOOST_UBLAS_INLINE
  2343. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2344. typename self_type::
  2345. #endif
  2346. iterator1 end () const {
  2347. return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
  2348. }
  2349. BOOST_UBLAS_INLINE
  2350. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2351. typename self_type::
  2352. #endif
  2353. reverse_iterator1 rbegin () const {
  2354. return reverse_iterator1 (end ());
  2355. }
  2356. BOOST_UBLAS_INLINE
  2357. #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2358. typename self_type::
  2359. #endif
  2360. reverse_iterator1 rend () const {
  2361. return reverse_iterator1 (begin ());
  2362. }
  2363. #endif
  2364. // Indices
  2365. BOOST_UBLAS_INLINE
  2366. size_type index1 () const {
  2367. return it2_.index1 ();
  2368. }
  2369. BOOST_UBLAS_INLINE
  2370. size_type index2 () const {
  2371. return it2_.index2 ();
  2372. }
  2373. // Assignment
  2374. BOOST_UBLAS_INLINE
  2375. iterator2 &operator = (const iterator2 &it) {
  2376. container_reference<self_type>::assign (&it ());
  2377. it2_ = it.it2_;
  2378. return *this;
  2379. }
  2380. // Comparison
  2381. BOOST_UBLAS_INLINE
  2382. bool operator == (const iterator2 &it) const {
  2383. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2384. return it2_ == it.it2_;
  2385. }
  2386. BOOST_UBLAS_INLINE
  2387. bool operator < (const iterator2 &it) const {
  2388. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2389. return it2_ < it.it2_;
  2390. }
  2391. private:
  2392. subiterator2_type it2_;
  2393. friend class const_iterator2;
  2394. };
  2395. #endif
  2396. BOOST_UBLAS_INLINE
  2397. iterator2 begin2 () {
  2398. return find2 (0, 0, 0);
  2399. }
  2400. BOOST_UBLAS_INLINE
  2401. iterator2 end2 () {
  2402. return find2 (0, 0, size2 ());
  2403. }
  2404. // Reverse iterators
  2405. BOOST_UBLAS_INLINE
  2406. const_reverse_iterator1 rbegin1 () const {
  2407. return const_reverse_iterator1 (end1 ());
  2408. }
  2409. BOOST_UBLAS_INLINE
  2410. const_reverse_iterator1 crbegin1 () const {
  2411. return rbegin1();
  2412. }
  2413. BOOST_UBLAS_INLINE
  2414. const_reverse_iterator1 rend1 () const {
  2415. return const_reverse_iterator1 (begin1 ());
  2416. }
  2417. BOOST_UBLAS_INLINE
  2418. const_reverse_iterator1 crend1 () const {
  2419. return rend1 ();
  2420. }
  2421. BOOST_UBLAS_INLINE
  2422. reverse_iterator1 rbegin1 () {
  2423. return reverse_iterator1 (end1 ());
  2424. }
  2425. BOOST_UBLAS_INLINE
  2426. reverse_iterator1 rend1 () {
  2427. return reverse_iterator1 (begin1 ());
  2428. }
  2429. BOOST_UBLAS_INLINE
  2430. const_reverse_iterator2 rbegin2 () const {
  2431. return const_reverse_iterator2 (end2 ());
  2432. }
  2433. BOOST_UBLAS_INLINE
  2434. const_reverse_iterator2 crbegin2 () const {
  2435. return rbegin2 ();
  2436. }
  2437. BOOST_UBLAS_INLINE
  2438. const_reverse_iterator2 rend2 () const {
  2439. return const_reverse_iterator2 (begin2 ());
  2440. }
  2441. BOOST_UBLAS_INLINE
  2442. const_reverse_iterator2 crend2 () const {
  2443. return rend2 ();
  2444. }
  2445. BOOST_UBLAS_INLINE
  2446. reverse_iterator2 rbegin2 () {
  2447. return reverse_iterator2 (end2 ());
  2448. }
  2449. BOOST_UBLAS_INLINE
  2450. reverse_iterator2 rend2 () {
  2451. return reverse_iterator2 (begin2 ());
  2452. }
  2453. private:
  2454. matrix_closure_type data_;
  2455. static value_type conj_;
  2456. };
  2457. template<class M, class TRI>
  2458. typename hermitian_adaptor<M, TRI>::value_type hermitian_adaptor<M, TRI>::conj_;
  2459. // Specialization for temporary_traits
  2460. template <class M, class TRI>
  2461. struct vector_temporary_traits< hermitian_adaptor<M, TRI> >
  2462. : vector_temporary_traits< M > {} ;
  2463. template <class M, class TRI>
  2464. struct vector_temporary_traits< const hermitian_adaptor<M, TRI> >
  2465. : vector_temporary_traits< M > {} ;
  2466. template <class M, class TRI>
  2467. struct matrix_temporary_traits< hermitian_adaptor<M, TRI> >
  2468. : matrix_temporary_traits< M > {} ;
  2469. template <class M, class TRI>
  2470. struct matrix_temporary_traits< const hermitian_adaptor<M, TRI> >
  2471. : matrix_temporary_traits< M > {} ;
  2472. }}}
  2473. #endif