iterator.hpp 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448
  1. //
  2. // Copyright (c) 2000-2002
  3. // Joerg Walter, Mathias Koch
  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_ITERATOR_
  13. #define _BOOST_UBLAS_ITERATOR_
  14. #include <boost/numeric/ublas/exception.hpp>
  15. #include <iterator>
  16. namespace boost { namespace numeric { namespace ublas {
  17. /** \brief Base class of all proxy classes that contain
  18. * a (redirectable) reference to an immutable object.
  19. *
  20. * \param C the type of the container referred to
  21. */
  22. template<class C>
  23. class container_const_reference:
  24. private nonassignable {
  25. public:
  26. typedef C container_type;
  27. BOOST_UBLAS_INLINE
  28. container_const_reference ():
  29. c_ (0) {}
  30. BOOST_UBLAS_INLINE
  31. container_const_reference (const container_type &c):
  32. c_ (&c) {}
  33. BOOST_UBLAS_INLINE
  34. const container_type &operator () () const {
  35. return *c_;
  36. }
  37. BOOST_UBLAS_INLINE
  38. container_const_reference &assign (const container_type *c) {
  39. c_ = c;
  40. return *this;
  41. }
  42. // Closure comparison
  43. BOOST_UBLAS_INLINE
  44. bool same_closure (const container_const_reference &cr) const {
  45. return c_ == cr.c_;
  46. }
  47. private:
  48. const container_type *c_;
  49. };
  50. /** \brief Base class of all proxy classes that contain
  51. * a (redirectable) reference to a mutable object.
  52. *
  53. * \param C the type of the container referred to
  54. */
  55. template<class C>
  56. class container_reference:
  57. private nonassignable {
  58. public:
  59. typedef C container_type;
  60. BOOST_UBLAS_INLINE
  61. container_reference ():
  62. c_ (0) {}
  63. BOOST_UBLAS_INLINE
  64. container_reference (container_type &c):
  65. c_ (&c) {}
  66. BOOST_UBLAS_INLINE
  67. container_type &operator () () const {
  68. return *c_;
  69. }
  70. BOOST_UBLAS_INLINE
  71. container_reference &assign (container_type *c) {
  72. c_ = c;
  73. return *this;
  74. }
  75. // Closure comparison
  76. BOOST_UBLAS_INLINE
  77. bool same_closure (const container_reference &cr) const {
  78. return c_ == cr.c_;
  79. }
  80. private:
  81. container_type *c_;
  82. };
  83. /** \brief Base class of all forward iterators.
  84. *
  85. * \param IC the iterator category
  86. * \param I the derived iterator type
  87. * \param T the value type
  88. *
  89. * The forward iterator can only proceed in one direction
  90. * via the post increment operator.
  91. */
  92. template<class IC, class I, class T>
  93. struct forward_iterator_base {
  94. typedef IC iterator_category;
  95. typedef T value_type;
  96. typedef std::ptrdiff_t difference_type;
  97. typedef T* pointer;
  98. typedef T& reference;
  99. typedef I derived_iterator_type;
  100. typedef T derived_value_type;
  101. // Arithmetic
  102. BOOST_UBLAS_INLINE
  103. derived_iterator_type operator ++ (int) {
  104. derived_iterator_type &d (*static_cast<const derived_iterator_type *> (this));
  105. derived_iterator_type tmp (d);
  106. ++ d;
  107. return tmp;
  108. }
  109. BOOST_UBLAS_INLINE
  110. friend derived_iterator_type operator ++ (derived_iterator_type &d, int) {
  111. derived_iterator_type tmp (d);
  112. ++ d;
  113. return tmp;
  114. }
  115. // Comparison
  116. BOOST_UBLAS_INLINE
  117. bool operator != (const derived_iterator_type &it) const {
  118. const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);
  119. return ! (*d == it);
  120. }
  121. };
  122. /** \brief Base class of all bidirectional iterators.
  123. *
  124. * \param IC the iterator category
  125. * \param I the derived iterator type
  126. * \param T the value type
  127. *
  128. * The bidirectional iterator can proceed in both directions
  129. * via the post increment and post decrement operator.
  130. */
  131. template<class IC, class I, class T>
  132. struct bidirectional_iterator_base {
  133. typedef IC iterator_category;
  134. typedef T value_type;
  135. typedef std::ptrdiff_t difference_type;
  136. typedef T* pointer;
  137. typedef T& reference;
  138. typedef I derived_iterator_type;
  139. typedef T derived_value_type;
  140. // Arithmetic
  141. BOOST_UBLAS_INLINE
  142. derived_iterator_type operator ++ (int) {
  143. derived_iterator_type &d (*static_cast<const derived_iterator_type *> (this));
  144. derived_iterator_type tmp (d);
  145. ++ d;
  146. return tmp;
  147. }
  148. BOOST_UBLAS_INLINE
  149. friend derived_iterator_type operator ++ (derived_iterator_type &d, int) {
  150. derived_iterator_type tmp (d);
  151. ++ d;
  152. return tmp;
  153. }
  154. BOOST_UBLAS_INLINE
  155. derived_iterator_type operator -- (int) {
  156. derived_iterator_type &d (*static_cast<const derived_iterator_type *> (this));
  157. derived_iterator_type tmp (d);
  158. -- d;
  159. return tmp;
  160. }
  161. BOOST_UBLAS_INLINE
  162. friend derived_iterator_type operator -- (derived_iterator_type &d, int) {
  163. derived_iterator_type tmp (d);
  164. -- d;
  165. return tmp;
  166. }
  167. // Comparison
  168. BOOST_UBLAS_INLINE
  169. bool operator != (const derived_iterator_type &it) const {
  170. const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);
  171. return ! (*d == it);
  172. }
  173. };
  174. /** \brief Base class of all random access iterators.
  175. *
  176. * \param IC the iterator category
  177. * \param I the derived iterator type
  178. * \param T the value type
  179. * \param D the difference type, default: std::ptrdiff_t
  180. *
  181. * The random access iterator can proceed in both directions
  182. * via the post increment/decrement operator or in larger steps
  183. * via the +, - and +=, -= operators. The random access iterator
  184. * is LessThan Comparable.
  185. */
  186. template<class IC, class I, class T, class D = std::ptrdiff_t>
  187. // ISSUE the default for D seems rather dangerous as it can easily be (silently) incorrect
  188. struct random_access_iterator_base {
  189. typedef IC iterator_category;
  190. typedef T value_type;
  191. typedef D difference_type;
  192. typedef T* pointer;
  193. typedef T& reference;
  194. typedef I derived_iterator_type;
  195. typedef T derived_value_type;
  196. typedef D derived_difference_type;
  197. /* FIXME Need to explicitly pass derived_reference_type as otherwise I undefined type or forward declared
  198. typedef typename derived_iterator_type::reference derived_reference_type;
  199. // Indexed element
  200. BOOST_UBLAS_INLINE
  201. derived_reference_type operator [] (derived_difference_type n) {
  202. return *(*this + n);
  203. }
  204. */
  205. // Arithmetic
  206. BOOST_UBLAS_INLINE
  207. derived_iterator_type operator ++ (int) {
  208. derived_iterator_type &d (*static_cast<derived_iterator_type *> (this));
  209. derived_iterator_type tmp (d);
  210. ++ d;
  211. return tmp;
  212. }
  213. BOOST_UBLAS_INLINE
  214. friend derived_iterator_type operator ++ (derived_iterator_type &d, int) {
  215. derived_iterator_type tmp (d);
  216. ++ d;
  217. return tmp;
  218. }
  219. BOOST_UBLAS_INLINE
  220. derived_iterator_type operator -- (int) {
  221. derived_iterator_type &d (*static_cast<derived_iterator_type *> (this));
  222. derived_iterator_type tmp (d);
  223. -- d;
  224. return tmp;
  225. }
  226. BOOST_UBLAS_INLINE
  227. friend derived_iterator_type operator -- (derived_iterator_type &d, int) {
  228. derived_iterator_type tmp (d);
  229. -- d;
  230. return tmp;
  231. }
  232. BOOST_UBLAS_INLINE
  233. derived_iterator_type operator + (derived_difference_type n) const {
  234. derived_iterator_type tmp (*static_cast<const derived_iterator_type *> (this));
  235. return tmp += n;
  236. }
  237. BOOST_UBLAS_INLINE
  238. friend derived_iterator_type operator + (const derived_iterator_type &d, derived_difference_type n) {
  239. derived_iterator_type tmp (d);
  240. return tmp += n;
  241. }
  242. BOOST_UBLAS_INLINE
  243. friend derived_iterator_type operator + (derived_difference_type n, const derived_iterator_type &d) {
  244. derived_iterator_type tmp (d);
  245. return tmp += n;
  246. }
  247. BOOST_UBLAS_INLINE
  248. derived_iterator_type operator - (derived_difference_type n) const {
  249. derived_iterator_type tmp (*static_cast<const derived_iterator_type *> (this));
  250. return tmp -= n;
  251. }
  252. BOOST_UBLAS_INLINE
  253. friend derived_iterator_type operator - (const derived_iterator_type &d, derived_difference_type n) {
  254. derived_iterator_type tmp (d);
  255. return tmp -= n;
  256. }
  257. // Comparison
  258. BOOST_UBLAS_INLINE
  259. bool operator != (const derived_iterator_type &it) const {
  260. const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);
  261. return ! (*d == it);
  262. }
  263. BOOST_UBLAS_INLINE
  264. bool operator <= (const derived_iterator_type &it) const {
  265. const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);
  266. return ! (it < *d);
  267. }
  268. BOOST_UBLAS_INLINE
  269. bool operator >= (const derived_iterator_type &it) const {
  270. const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);
  271. return ! (*d < it);
  272. }
  273. BOOST_UBLAS_INLINE
  274. bool operator > (const derived_iterator_type &it) const {
  275. const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this);
  276. return it < *d;
  277. }
  278. };
  279. /** \brief Base class of all reverse iterators. (non-MSVC version)
  280. *
  281. * \param I the derived iterator type
  282. * \param T the value type
  283. * \param R the reference type
  284. *
  285. * The reverse iterator implements a bidirectional iterator
  286. * reversing the elements of the underlying iterator. It
  287. * implements most operators of a random access iterator.
  288. *
  289. * uBLAS extension: it.index()
  290. */
  291. // Renamed this class from reverse_iterator to get
  292. // typedef reverse_iterator<...> reverse_iterator
  293. // working. Thanks to Gabriel Dos Reis for explaining this.
  294. template <class I>
  295. class reverse_iterator_base:
  296. public std::reverse_iterator<I> {
  297. public:
  298. typedef typename I::container_type container_type;
  299. typedef typename container_type::size_type size_type;
  300. typedef typename I::difference_type difference_type;
  301. typedef I iterator_type;
  302. // Construction and destruction
  303. BOOST_UBLAS_INLINE
  304. reverse_iterator_base ():
  305. std::reverse_iterator<iterator_type> () {}
  306. BOOST_UBLAS_INLINE
  307. reverse_iterator_base (const iterator_type &it):
  308. std::reverse_iterator<iterator_type> (it) {}
  309. // Arithmetic
  310. BOOST_UBLAS_INLINE
  311. reverse_iterator_base &operator ++ () {
  312. return *this = -- this->base ();
  313. }
  314. BOOST_UBLAS_INLINE
  315. reverse_iterator_base operator ++ (int) {
  316. reverse_iterator_base tmp (*this);
  317. *this = -- this->base ();
  318. return tmp;
  319. }
  320. BOOST_UBLAS_INLINE
  321. reverse_iterator_base &operator -- () {
  322. return *this = ++ this->base ();
  323. }
  324. BOOST_UBLAS_INLINE
  325. reverse_iterator_base operator -- (int) {
  326. reverse_iterator_base tmp (*this);
  327. *this = ++ this->base ();
  328. return tmp;
  329. }
  330. BOOST_UBLAS_INLINE
  331. reverse_iterator_base &operator += (difference_type n) {
  332. return *this = this->base () - n;
  333. }
  334. BOOST_UBLAS_INLINE
  335. reverse_iterator_base &operator -= (difference_type n) {
  336. return *this = this->base () + n;
  337. }
  338. BOOST_UBLAS_INLINE
  339. friend reverse_iterator_base operator + (const reverse_iterator_base &it, difference_type n) {
  340. reverse_iterator_base tmp (it);
  341. return tmp += n;
  342. }
  343. BOOST_UBLAS_INLINE
  344. friend reverse_iterator_base operator + (difference_type n, const reverse_iterator_base &it) {
  345. reverse_iterator_base tmp (it);
  346. return tmp += n;
  347. }
  348. BOOST_UBLAS_INLINE
  349. friend reverse_iterator_base operator - (const reverse_iterator_base &it, difference_type n) {
  350. reverse_iterator_base tmp (it);
  351. return tmp -= n;
  352. }
  353. BOOST_UBLAS_INLINE
  354. friend difference_type operator - (const reverse_iterator_base &it1, const reverse_iterator_base &it2) {
  355. return it2.base () - it1.base ();
  356. }
  357. BOOST_UBLAS_INLINE
  358. const container_type &operator () () const {
  359. return this->base () ();
  360. }
  361. BOOST_UBLAS_INLINE
  362. size_type index () const {
  363. iterator_type tmp (this->base ());
  364. return (-- tmp).index ();
  365. }
  366. };
  367. /** \brief 1st base class of all matrix reverse iterators. (non-MSVC version)
  368. *
  369. * \param I the derived iterator type
  370. *
  371. * The reverse iterator implements a bidirectional iterator
  372. * reversing the elements of the underlying iterator. It
  373. * implements most operators of a random access iterator.
  374. *
  375. * uBLAS extension: it.index1(), it.index2() and access to
  376. * the dual iterator via begin(), end(), rbegin(), rend()
  377. */
  378. // Renamed this class from reverse_iterator1 to get
  379. // typedef reverse_iterator1<...> reverse_iterator1
  380. // working. Thanks to Gabriel Dos Reis for explaining this.
  381. template <class I>
  382. class reverse_iterator_base1:
  383. public std::reverse_iterator<I> {
  384. public:
  385. typedef typename I::container_type container_type;
  386. typedef typename container_type::size_type size_type;
  387. typedef typename I::difference_type difference_type;
  388. typedef I iterator_type;
  389. typedef typename I::dual_iterator_type dual_iterator_type;
  390. typedef typename I::dual_reverse_iterator_type dual_reverse_iterator_type;
  391. // Construction and destruction
  392. BOOST_UBLAS_INLINE
  393. reverse_iterator_base1 ():
  394. std::reverse_iterator<iterator_type> () {}
  395. BOOST_UBLAS_INLINE
  396. reverse_iterator_base1 (const iterator_type &it):
  397. std::reverse_iterator<iterator_type> (it) {}
  398. // Arithmetic
  399. BOOST_UBLAS_INLINE
  400. reverse_iterator_base1 &operator ++ () {
  401. return *this = -- this->base ();
  402. }
  403. BOOST_UBLAS_INLINE
  404. reverse_iterator_base1 operator ++ (int) {
  405. reverse_iterator_base1 tmp (*this);
  406. *this = -- this->base ();
  407. return tmp;
  408. }
  409. BOOST_UBLAS_INLINE
  410. reverse_iterator_base1 &operator -- () {
  411. return *this = ++ this->base ();
  412. }
  413. BOOST_UBLAS_INLINE
  414. reverse_iterator_base1 operator -- (int) {
  415. reverse_iterator_base1 tmp (*this);
  416. *this = ++ this->base ();
  417. return tmp;
  418. }
  419. BOOST_UBLAS_INLINE
  420. reverse_iterator_base1 &operator += (difference_type n) {
  421. return *this = this->base () - n;
  422. }
  423. BOOST_UBLAS_INLINE
  424. reverse_iterator_base1 &operator -= (difference_type n) {
  425. return *this = this->base () + n;
  426. }
  427. BOOST_UBLAS_INLINE
  428. friend reverse_iterator_base1 operator + (const reverse_iterator_base1 &it, difference_type n) {
  429. reverse_iterator_base1 tmp (it);
  430. return tmp += n;
  431. }
  432. BOOST_UBLAS_INLINE
  433. friend reverse_iterator_base1 operator + (difference_type n, const reverse_iterator_base1 &it) {
  434. reverse_iterator_base1 tmp (it);
  435. return tmp += n;
  436. }
  437. BOOST_UBLAS_INLINE
  438. friend reverse_iterator_base1 operator - (const reverse_iterator_base1 &it, difference_type n) {
  439. reverse_iterator_base1 tmp (it);
  440. return tmp -= n;
  441. }
  442. BOOST_UBLAS_INLINE
  443. friend difference_type operator - (const reverse_iterator_base1 &it1, const reverse_iterator_base1 &it2) {
  444. return it2.base () - it1.base ();
  445. }
  446. BOOST_UBLAS_INLINE
  447. const container_type &operator () () const {
  448. return this->base () ();
  449. }
  450. BOOST_UBLAS_INLINE
  451. size_type index1 () const {
  452. iterator_type tmp (this->base ());
  453. return (-- tmp).index1 ();
  454. }
  455. BOOST_UBLAS_INLINE
  456. size_type index2 () const {
  457. iterator_type tmp (this->base ());
  458. return (-- tmp).index2 ();
  459. }
  460. BOOST_UBLAS_INLINE
  461. dual_iterator_type begin () const {
  462. iterator_type tmp (this->base ());
  463. return (-- tmp).begin ();
  464. }
  465. BOOST_UBLAS_INLINE
  466. dual_iterator_type end () const {
  467. iterator_type tmp (this->base ());
  468. return (-- tmp).end ();
  469. }
  470. BOOST_UBLAS_INLINE
  471. dual_reverse_iterator_type rbegin () const {
  472. return dual_reverse_iterator_type (end ());
  473. }
  474. BOOST_UBLAS_INLINE
  475. dual_reverse_iterator_type rend () const {
  476. return dual_reverse_iterator_type (begin ());
  477. }
  478. };
  479. /** \brief 2nd base class of all matrix reverse iterators. (non-MSVC version)
  480. *
  481. * \param I the derived iterator type
  482. *
  483. * The reverse iterator implements a bidirectional iterator
  484. * reversing the elements of the underlying iterator. It
  485. * implements most operators of a random access iterator.
  486. *
  487. * uBLAS extension: it.index1(), it.index2() and access to
  488. * the dual iterator via begin(), end(), rbegin(), rend()
  489. *
  490. * Note: this type is _identical_ to reverse_iterator_base1
  491. */
  492. // Renamed this class from reverse_iterator2 to get
  493. // typedef reverse_iterator2<...> reverse_iterator2
  494. // working. Thanks to Gabriel Dos Reis for explaining this.
  495. template <class I>
  496. class reverse_iterator_base2:
  497. public std::reverse_iterator<I> {
  498. public:
  499. typedef typename I::container_type container_type;
  500. typedef typename container_type::size_type size_type;
  501. typedef typename I::difference_type difference_type;
  502. typedef I iterator_type;
  503. typedef typename I::dual_iterator_type dual_iterator_type;
  504. typedef typename I::dual_reverse_iterator_type dual_reverse_iterator_type;
  505. // Construction and destruction
  506. BOOST_UBLAS_INLINE
  507. reverse_iterator_base2 ():
  508. std::reverse_iterator<iterator_type> () {}
  509. BOOST_UBLAS_INLINE
  510. reverse_iterator_base2 (const iterator_type &it):
  511. std::reverse_iterator<iterator_type> (it) {}
  512. // Arithmetic
  513. BOOST_UBLAS_INLINE
  514. reverse_iterator_base2 &operator ++ () {
  515. return *this = -- this->base ();
  516. }
  517. BOOST_UBLAS_INLINE
  518. reverse_iterator_base2 operator ++ (int) {
  519. reverse_iterator_base2 tmp (*this);
  520. *this = -- this->base ();
  521. return tmp;
  522. }
  523. BOOST_UBLAS_INLINE
  524. reverse_iterator_base2 &operator -- () {
  525. return *this = ++ this->base ();
  526. }
  527. BOOST_UBLAS_INLINE
  528. reverse_iterator_base2 operator -- (int) {
  529. reverse_iterator_base2 tmp (*this);
  530. *this = ++ this->base ();
  531. return tmp;
  532. }
  533. BOOST_UBLAS_INLINE
  534. reverse_iterator_base2 &operator += (difference_type n) {
  535. return *this = this->base () - n;
  536. }
  537. BOOST_UBLAS_INLINE
  538. reverse_iterator_base2 &operator -= (difference_type n) {
  539. return *this = this->base () + n;
  540. }
  541. BOOST_UBLAS_INLINE
  542. friend reverse_iterator_base2 operator + (const reverse_iterator_base2 &it, difference_type n) {
  543. reverse_iterator_base2 tmp (it);
  544. return tmp += n;
  545. }
  546. BOOST_UBLAS_INLINE
  547. friend reverse_iterator_base2 operator + (difference_type n, const reverse_iterator_base2 &it) {
  548. reverse_iterator_base2 tmp (it);
  549. return tmp += n;
  550. }
  551. BOOST_UBLAS_INLINE
  552. friend reverse_iterator_base2 operator - (const reverse_iterator_base2 &it, difference_type n) {
  553. reverse_iterator_base2 tmp (it);
  554. return tmp -= n;
  555. }
  556. BOOST_UBLAS_INLINE
  557. friend difference_type operator - (const reverse_iterator_base2 &it1, const reverse_iterator_base2 &it2) {
  558. return it2.base () - it1.base ();
  559. }
  560. BOOST_UBLAS_INLINE
  561. const container_type &operator () () const {
  562. return this->base () ();
  563. }
  564. BOOST_UBLAS_INLINE
  565. size_type index1 () const {
  566. iterator_type tmp (this->base ());
  567. return (-- tmp).index1 ();
  568. }
  569. BOOST_UBLAS_INLINE
  570. size_type index2 () const {
  571. iterator_type tmp (this->base ());
  572. return (-- tmp).index2 ();
  573. }
  574. BOOST_UBLAS_INLINE
  575. dual_iterator_type begin () const {
  576. iterator_type tmp (this->base ());
  577. return (-- tmp).begin ();
  578. }
  579. BOOST_UBLAS_INLINE
  580. dual_iterator_type end () const {
  581. iterator_type tmp (this->base ());
  582. return (-- tmp).end ();
  583. }
  584. BOOST_UBLAS_INLINE
  585. dual_reverse_iterator_type rbegin () const {
  586. return dual_reverse_iterator_type (end ());
  587. }
  588. BOOST_UBLAS_INLINE
  589. dual_reverse_iterator_type rend () const {
  590. return dual_reverse_iterator_type (begin ());
  591. }
  592. };
  593. /** \brief A class implementing an indexed random access iterator.
  594. *
  595. * \param C the (mutable) container type
  596. * \param IC the iterator category
  597. *
  598. * This class implements a random access iterator. The current
  599. * position is stored as the unsigned integer it_ and the
  600. * values are accessed via operator()(it_) of the container.
  601. *
  602. * uBLAS extension: index()
  603. */
  604. template<class C, class IC>
  605. class indexed_iterator:
  606. public container_reference<C>,
  607. public random_access_iterator_base<IC,
  608. indexed_iterator<C, IC>,
  609. typename C::value_type,
  610. typename C::difference_type> {
  611. public:
  612. typedef C container_type;
  613. typedef IC iterator_category;
  614. typedef typename container_type::size_type size_type;
  615. typedef typename container_type::difference_type difference_type;
  616. typedef typename container_type::value_type value_type;
  617. typedef typename container_type::reference reference;
  618. // Construction and destruction
  619. BOOST_UBLAS_INLINE
  620. indexed_iterator ():
  621. container_reference<container_type> (), it_ () {}
  622. BOOST_UBLAS_INLINE
  623. indexed_iterator (container_type &c, size_type it):
  624. container_reference<container_type> (c), it_ (it) {}
  625. // Arithmetic
  626. BOOST_UBLAS_INLINE
  627. indexed_iterator &operator ++ () {
  628. ++ it_;
  629. return *this;
  630. }
  631. BOOST_UBLAS_INLINE
  632. indexed_iterator &operator -- () {
  633. -- it_;
  634. return *this;
  635. }
  636. BOOST_UBLAS_INLINE
  637. indexed_iterator &operator += (difference_type n) {
  638. it_ += n;
  639. return *this;
  640. }
  641. BOOST_UBLAS_INLINE
  642. indexed_iterator &operator -= (difference_type n) {
  643. it_ -= n;
  644. return *this;
  645. }
  646. BOOST_UBLAS_INLINE
  647. difference_type operator - (const indexed_iterator &it) const {
  648. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  649. return it_ - it.it_;
  650. }
  651. // Dereference
  652. BOOST_UBLAS_INLINE
  653. reference operator * () const {
  654. BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
  655. return (*this) () (it_);
  656. }
  657. BOOST_UBLAS_INLINE
  658. reference operator [] (difference_type n) const {
  659. return *((*this) + n);
  660. }
  661. // Index
  662. BOOST_UBLAS_INLINE
  663. size_type index () const {
  664. return it_;
  665. }
  666. // Assignment
  667. BOOST_UBLAS_INLINE
  668. indexed_iterator &operator = (const indexed_iterator &it) {
  669. // FIX: ICC needs full qualification?!
  670. // assign (&it ());
  671. container_reference<C>::assign (&it ());
  672. it_ = it.it_;
  673. return *this;
  674. }
  675. // Comparison
  676. BOOST_UBLAS_INLINE
  677. bool operator == (const indexed_iterator &it) const {
  678. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  679. return it_ == it.it_;
  680. }
  681. BOOST_UBLAS_INLINE
  682. bool operator < (const indexed_iterator &it) const {
  683. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  684. return it_ < it.it_;
  685. }
  686. private:
  687. size_type it_;
  688. };
  689. /** \brief A class implementing an indexed random access iterator.
  690. *
  691. * \param C the (immutable) container type
  692. * \param IC the iterator category
  693. *
  694. * This class implements a random access iterator. The current
  695. * position is stored as the unsigned integer \c it_ and the
  696. * values are accessed via \c operator()(it_) of the container.
  697. *
  698. * uBLAS extension: \c index()
  699. *
  700. * Note: there is an automatic conversion from
  701. * \c indexed_iterator to \c indexed_const_iterator
  702. */
  703. template<class C, class IC>
  704. class indexed_const_iterator:
  705. public container_const_reference<C>,
  706. public random_access_iterator_base<IC,
  707. indexed_const_iterator<C, IC>,
  708. typename C::value_type,
  709. typename C::difference_type> {
  710. public:
  711. typedef C container_type;
  712. typedef IC iterator_category;
  713. typedef typename container_type::size_type size_type;
  714. typedef typename container_type::difference_type difference_type;
  715. typedef typename container_type::value_type value_type;
  716. typedef typename container_type::const_reference reference;
  717. typedef indexed_iterator<container_type, iterator_category> iterator_type;
  718. // Construction and destruction
  719. BOOST_UBLAS_INLINE
  720. indexed_const_iterator ():
  721. container_const_reference<container_type> (), it_ () {}
  722. BOOST_UBLAS_INLINE
  723. indexed_const_iterator (const container_type &c, size_type it):
  724. container_const_reference<container_type> (c), it_ (it) {}
  725. BOOST_UBLAS_INLINE
  726. indexed_const_iterator (const iterator_type &it):
  727. container_const_reference<container_type> (it ()), it_ (it.index ()) {}
  728. // Arithmetic
  729. BOOST_UBLAS_INLINE
  730. indexed_const_iterator &operator ++ () {
  731. ++ it_;
  732. return *this;
  733. }
  734. BOOST_UBLAS_INLINE
  735. indexed_const_iterator &operator -- () {
  736. -- it_;
  737. return *this;
  738. }
  739. BOOST_UBLAS_INLINE
  740. indexed_const_iterator &operator += (difference_type n) {
  741. it_ += n;
  742. return *this;
  743. }
  744. BOOST_UBLAS_INLINE
  745. indexed_const_iterator &operator -= (difference_type n) {
  746. it_ -= n;
  747. return *this;
  748. }
  749. BOOST_UBLAS_INLINE
  750. difference_type operator - (const indexed_const_iterator &it) const {
  751. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  752. return it_ - it.it_;
  753. }
  754. // Dereference
  755. BOOST_UBLAS_INLINE
  756. reference operator * () const {
  757. BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
  758. return (*this) () (it_);
  759. }
  760. BOOST_UBLAS_INLINE
  761. reference operator [] (difference_type n) const {
  762. return *((*this) + n);
  763. }
  764. // Index
  765. BOOST_UBLAS_INLINE
  766. size_type index () const {
  767. return it_;
  768. }
  769. // Assignment
  770. BOOST_UBLAS_INLINE
  771. indexed_const_iterator &operator = (const indexed_const_iterator &it) {
  772. // FIX: ICC needs full qualification?!
  773. // assign (&it ());
  774. container_const_reference<C>::assign (&it ());
  775. it_ = it.it_;
  776. return *this;
  777. }
  778. // Comparison
  779. BOOST_UBLAS_INLINE
  780. bool operator == (const indexed_const_iterator &it) const {
  781. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  782. return it_ == it.it_;
  783. }
  784. BOOST_UBLAS_INLINE
  785. bool operator < (const indexed_const_iterator &it) const {
  786. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  787. return it_ < it.it_;
  788. }
  789. private:
  790. size_type it_;
  791. friend class indexed_iterator<container_type, iterator_category>;
  792. };
  793. template<class C, class IC>
  794. class indexed_iterator2;
  795. /** \brief A class implementing an indexed random access iterator
  796. * of a matrix.
  797. *
  798. * \param C the (mutable) container type
  799. * \param IC the iterator category
  800. *
  801. * This class implements a random access iterator. The current
  802. * position is stored as two unsigned integers \c it1_ and \c it2_
  803. * and the values are accessed via \c operator()(it1_, it2_) of the
  804. * container. The iterator changes the first index.
  805. *
  806. * uBLAS extension: \c index1(), \c index2() and access to the
  807. * dual iterator via \c begin(), \c end(), \c rbegin() and \c rend()
  808. *
  809. * Note: The container has to support the \code find2(rank, i, j) \endcode
  810. * method
  811. */
  812. template<class C, class IC>
  813. class indexed_iterator1:
  814. public container_reference<C>,
  815. public random_access_iterator_base<IC,
  816. indexed_iterator1<C, IC>,
  817. typename C::value_type,
  818. typename C::difference_type> {
  819. public:
  820. typedef C container_type;
  821. typedef IC iterator_category;
  822. typedef typename container_type::size_type size_type;
  823. typedef typename container_type::difference_type difference_type;
  824. typedef typename container_type::value_type value_type;
  825. typedef typename container_type::reference reference;
  826. typedef indexed_iterator2<container_type, iterator_category> dual_iterator_type;
  827. typedef reverse_iterator_base2<dual_iterator_type> dual_reverse_iterator_type;
  828. // Construction and destruction
  829. BOOST_UBLAS_INLINE
  830. indexed_iterator1 ():
  831. container_reference<container_type> (), it1_ (), it2_ () {}
  832. BOOST_UBLAS_INLINE
  833. indexed_iterator1 (container_type &c, size_type it1, size_type it2):
  834. container_reference<container_type> (c), it1_ (it1), it2_ (it2) {}
  835. // Arithmetic
  836. BOOST_UBLAS_INLINE
  837. indexed_iterator1 &operator ++ () {
  838. ++ it1_;
  839. return *this;
  840. }
  841. BOOST_UBLAS_INLINE
  842. indexed_iterator1 &operator -- () {
  843. -- it1_;
  844. return *this;
  845. }
  846. BOOST_UBLAS_INLINE
  847. indexed_iterator1 &operator += (difference_type n) {
  848. it1_ += n;
  849. return *this;
  850. }
  851. BOOST_UBLAS_INLINE
  852. indexed_iterator1 &operator -= (difference_type n) {
  853. it1_ -= n;
  854. return *this;
  855. }
  856. BOOST_UBLAS_INLINE
  857. difference_type operator - (const indexed_iterator1 &it) const {
  858. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  859. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  860. return it1_ - it.it1_;
  861. }
  862. // Dereference
  863. BOOST_UBLAS_INLINE
  864. reference operator * () const {
  865. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  866. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  867. return (*this) () (it1_, it2_);
  868. }
  869. BOOST_UBLAS_INLINE
  870. reference operator [] (difference_type n) const {
  871. return *((*this) + n);
  872. }
  873. // Index
  874. BOOST_UBLAS_INLINE
  875. size_type index1 () const {
  876. return it1_;
  877. }
  878. BOOST_UBLAS_INLINE
  879. size_type index2 () const {
  880. return it2_;
  881. }
  882. BOOST_UBLAS_INLINE
  883. dual_iterator_type begin () const {
  884. return (*this) ().find2 (1, index1 (), 0);
  885. }
  886. BOOST_UBLAS_INLINE
  887. dual_iterator_type end () const {
  888. return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
  889. }
  890. BOOST_UBLAS_INLINE
  891. dual_reverse_iterator_type rbegin () const {
  892. return dual_reverse_iterator_type (end ());
  893. }
  894. BOOST_UBLAS_INLINE
  895. dual_reverse_iterator_type rend () const {
  896. return dual_reverse_iterator_type (begin ());
  897. }
  898. // Assignment
  899. BOOST_UBLAS_INLINE
  900. indexed_iterator1 &operator = (const indexed_iterator1 &it) {
  901. // FIX: ICC needs full qualification?!
  902. // assign (&it ());
  903. container_reference<C>::assign (&it ());
  904. it1_ = it.it1_;
  905. it2_ = it.it2_;
  906. return *this;
  907. }
  908. // Comparison
  909. BOOST_UBLAS_INLINE
  910. bool operator == (const indexed_iterator1 &it) const {
  911. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  912. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  913. return it1_ == it.it1_;
  914. }
  915. BOOST_UBLAS_INLINE
  916. bool operator < (const indexed_iterator1 &it) const {
  917. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  918. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  919. return it1_ < it.it1_;
  920. }
  921. private:
  922. size_type it1_;
  923. size_type it2_;
  924. };
  925. template<class C, class IC>
  926. class indexed_const_iterator2;
  927. /** \brief A class implementing an indexed random access iterator
  928. * of a matrix.
  929. *
  930. * \param C the (immutable) container type
  931. * \param IC the iterator category
  932. *
  933. * This class implements a random access iterator. The current
  934. * position is stored as two unsigned integers \c it1_ and \c it2_
  935. * and the values are accessed via \c operator()(it1_, it2_) of the
  936. * container. The iterator changes the first index.
  937. *
  938. * uBLAS extension: \c index1(), \c index2() and access to the
  939. * dual iterator via \c begin(), \c end(), \c rbegin() and \c rend()
  940. *
  941. * Note 1: The container has to support the find2(rank, i, j) method
  942. *
  943. * Note 2: there is an automatic conversion from
  944. * \c indexed_iterator1 to \c indexed_const_iterator1
  945. */
  946. template<class C, class IC>
  947. class indexed_const_iterator1:
  948. public container_const_reference<C>,
  949. public random_access_iterator_base<IC,
  950. indexed_const_iterator1<C, IC>,
  951. typename C::value_type,
  952. typename C::difference_type> {
  953. public:
  954. typedef C container_type;
  955. typedef IC iterator_category;
  956. typedef typename container_type::size_type size_type;
  957. typedef typename container_type::difference_type difference_type;
  958. typedef typename container_type::value_type value_type;
  959. typedef typename container_type::const_reference reference;
  960. typedef indexed_iterator1<container_type, iterator_category> iterator_type;
  961. typedef indexed_const_iterator2<container_type, iterator_category> dual_iterator_type;
  962. typedef reverse_iterator_base2<dual_iterator_type> dual_reverse_iterator_type;
  963. // Construction and destruction
  964. BOOST_UBLAS_INLINE
  965. indexed_const_iterator1 ():
  966. container_const_reference<container_type> (), it1_ (), it2_ () {}
  967. BOOST_UBLAS_INLINE
  968. indexed_const_iterator1 (const container_type &c, size_type it1, size_type it2):
  969. container_const_reference<container_type> (c), it1_ (it1), it2_ (it2) {}
  970. BOOST_UBLAS_INLINE
  971. indexed_const_iterator1 (const iterator_type &it):
  972. container_const_reference<container_type> (it ()), it1_ (it.index1 ()), it2_ (it.index2 ()) {}
  973. // Arithmetic
  974. BOOST_UBLAS_INLINE
  975. indexed_const_iterator1 &operator ++ () {
  976. ++ it1_;
  977. return *this;
  978. }
  979. BOOST_UBLAS_INLINE
  980. indexed_const_iterator1 &operator -- () {
  981. -- it1_;
  982. return *this;
  983. }
  984. BOOST_UBLAS_INLINE
  985. indexed_const_iterator1 &operator += (difference_type n) {
  986. it1_ += n;
  987. return *this;
  988. }
  989. BOOST_UBLAS_INLINE
  990. indexed_const_iterator1 &operator -= (difference_type n) {
  991. it1_ -= n;
  992. return *this;
  993. }
  994. BOOST_UBLAS_INLINE
  995. difference_type operator - (const indexed_const_iterator1 &it) const {
  996. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  997. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  998. return it1_ - it.it1_;
  999. }
  1000. // Dereference
  1001. BOOST_UBLAS_INLINE
  1002. reference operator * () const {
  1003. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  1004. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  1005. return (*this) () (it1_, it2_);
  1006. }
  1007. BOOST_UBLAS_INLINE
  1008. reference operator [] (difference_type n) const {
  1009. return *((*this) + n);
  1010. }
  1011. // Index
  1012. BOOST_UBLAS_INLINE
  1013. size_type index1 () const {
  1014. return it1_;
  1015. }
  1016. BOOST_UBLAS_INLINE
  1017. size_type index2 () const {
  1018. return it2_;
  1019. }
  1020. BOOST_UBLAS_INLINE
  1021. dual_iterator_type begin () const {
  1022. return (*this) ().find2 (1, index1 (), 0);
  1023. }
  1024. BOOST_UBLAS_INLINE
  1025. dual_iterator_type end () const {
  1026. return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
  1027. }
  1028. BOOST_UBLAS_INLINE
  1029. dual_reverse_iterator_type rbegin () const {
  1030. return dual_reverse_iterator_type (end ());
  1031. }
  1032. BOOST_UBLAS_INLINE
  1033. dual_reverse_iterator_type rend () const {
  1034. return dual_reverse_iterator_type (begin ());
  1035. }
  1036. // Assignment
  1037. BOOST_UBLAS_INLINE
  1038. indexed_const_iterator1 &operator = (const indexed_const_iterator1 &it) {
  1039. // FIX: ICC needs full qualification?!
  1040. // assign (&it ());
  1041. container_const_reference<C>::assign (&it ());
  1042. it1_ = it.it1_;
  1043. it2_ = it.it2_;
  1044. return *this;
  1045. }
  1046. // Comparison
  1047. BOOST_UBLAS_INLINE
  1048. bool operator == (const indexed_const_iterator1 &it) const {
  1049. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1050. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  1051. return it1_ == it.it1_;
  1052. }
  1053. BOOST_UBLAS_INLINE
  1054. bool operator < (const indexed_const_iterator1 &it) const {
  1055. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1056. BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  1057. return it1_ < it.it1_;
  1058. }
  1059. private:
  1060. size_type it1_;
  1061. size_type it2_;
  1062. friend class indexed_iterator1<container_type, iterator_category>;
  1063. };
  1064. /** \brief A class implementing an indexed random access iterator
  1065. * of a matrix.
  1066. *
  1067. * \param C the (mutable) container type
  1068. * \param IC the iterator category
  1069. *
  1070. * This class implements a random access iterator. The current
  1071. * position is stored as two unsigned integers \c it1_ and \c it2_
  1072. * and the values are accessed via \c operator()(it1_, it2_) of the
  1073. * container. The iterator changes the second index.
  1074. *
  1075. * uBLAS extension: \c index1(), \c index2() and access to the
  1076. * dual iterator via \c begin(), \c end(), \c rbegin() and \c rend()
  1077. *
  1078. * Note: The container has to support the find1(rank, i, j) method
  1079. */
  1080. template<class C, class IC>
  1081. class indexed_iterator2:
  1082. public container_reference<C>,
  1083. public random_access_iterator_base<IC,
  1084. indexed_iterator2<C, IC>,
  1085. typename C::value_type,
  1086. typename C::difference_type> {
  1087. public:
  1088. typedef C container_type;
  1089. typedef IC iterator_category;
  1090. typedef typename container_type::size_type size_type;
  1091. typedef typename container_type::difference_type difference_type;
  1092. typedef typename container_type::value_type value_type;
  1093. typedef typename container_type::reference reference;
  1094. typedef indexed_iterator1<container_type, iterator_category> dual_iterator_type;
  1095. typedef reverse_iterator_base1<dual_iterator_type> dual_reverse_iterator_type;
  1096. // Construction and destruction
  1097. BOOST_UBLAS_INLINE
  1098. indexed_iterator2 ():
  1099. container_reference<container_type> (), it1_ (), it2_ () {}
  1100. BOOST_UBLAS_INLINE
  1101. indexed_iterator2 (container_type &c, size_type it1, size_type it2):
  1102. container_reference<container_type> (c), it1_ (it1), it2_ (it2) {}
  1103. // Arithmetic
  1104. BOOST_UBLAS_INLINE
  1105. indexed_iterator2 &operator ++ () {
  1106. ++ it2_;
  1107. return *this;
  1108. }
  1109. BOOST_UBLAS_INLINE
  1110. indexed_iterator2 &operator -- () {
  1111. -- it2_;
  1112. return *this;
  1113. }
  1114. BOOST_UBLAS_INLINE
  1115. indexed_iterator2 &operator += (difference_type n) {
  1116. it2_ += n;
  1117. return *this;
  1118. }
  1119. BOOST_UBLAS_INLINE
  1120. indexed_iterator2 &operator -= (difference_type n) {
  1121. it2_ -= n;
  1122. return *this;
  1123. }
  1124. BOOST_UBLAS_INLINE
  1125. difference_type operator - (const indexed_iterator2 &it) const {
  1126. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1127. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  1128. return it2_ - it.it2_;
  1129. }
  1130. // Dereference
  1131. BOOST_UBLAS_INLINE
  1132. reference operator * () const {
  1133. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  1134. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  1135. return (*this) () (it1_, it2_);
  1136. }
  1137. BOOST_UBLAS_INLINE
  1138. reference operator [] (difference_type n) const {
  1139. return *((*this) + n);
  1140. }
  1141. // Index
  1142. BOOST_UBLAS_INLINE
  1143. size_type index1 () const {
  1144. return it1_;
  1145. }
  1146. BOOST_UBLAS_INLINE
  1147. size_type index2 () const {
  1148. return it2_;
  1149. }
  1150. BOOST_UBLAS_INLINE
  1151. dual_iterator_type begin () const {
  1152. return (*this) ().find1 (1, 0, index2 ());
  1153. }
  1154. BOOST_UBLAS_INLINE
  1155. dual_iterator_type end () const {
  1156. return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
  1157. }
  1158. BOOST_UBLAS_INLINE
  1159. dual_reverse_iterator_type rbegin () const {
  1160. return dual_reverse_iterator_type (end ());
  1161. }
  1162. BOOST_UBLAS_INLINE
  1163. dual_reverse_iterator_type rend () const {
  1164. return dual_reverse_iterator_type (begin ());
  1165. }
  1166. // Assignment
  1167. BOOST_UBLAS_INLINE
  1168. indexed_iterator2 &operator = (const indexed_iterator2 &it) {
  1169. // FIX: ICC needs full qualification?!
  1170. // assign (&it ());
  1171. container_reference<C>::assign (&it ());
  1172. it1_ = it.it1_;
  1173. it2_ = it.it2_;
  1174. return *this;
  1175. }
  1176. // Comparison
  1177. BOOST_UBLAS_INLINE
  1178. bool operator == (const indexed_iterator2 &it) const {
  1179. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1180. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  1181. return it2_ == it.it2_;
  1182. }
  1183. BOOST_UBLAS_INLINE
  1184. bool operator < (const indexed_iterator2 &it) const {
  1185. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1186. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  1187. return it2_ < it.it2_;
  1188. }
  1189. private:
  1190. size_type it1_;
  1191. size_type it2_;
  1192. };
  1193. /** \brief A class implementing an indexed random access iterator
  1194. * of a matrix.
  1195. *
  1196. * \param C the (immutable) container type
  1197. * \param IC the iterator category
  1198. *
  1199. * This class implements a random access iterator. The current
  1200. * position is stored as two unsigned integers \c it1_ and \c it2_
  1201. * and the values are accessed via \c operator()(it1_, it2_) of the
  1202. * container. The iterator changes the second index.
  1203. *
  1204. * uBLAS extension: \c index1(), \c index2() and access to the
  1205. * dual iterator via \c begin(), \c end(), \c rbegin() and \c rend()
  1206. *
  1207. * Note 1: The container has to support the \c find2(rank, i, j) method
  1208. *
  1209. * Note 2: there is an automatic conversion from
  1210. * \c indexed_iterator2 to \c indexed_const_iterator2
  1211. */
  1212. template<class C, class IC>
  1213. class indexed_const_iterator2:
  1214. public container_const_reference<C>,
  1215. public random_access_iterator_base<IC,
  1216. indexed_const_iterator2<C, IC>,
  1217. typename C::value_type,
  1218. typename C::difference_type> {
  1219. public:
  1220. typedef C container_type;
  1221. typedef IC iterator_category;
  1222. typedef typename container_type::size_type size_type;
  1223. typedef typename container_type::difference_type difference_type;
  1224. typedef typename container_type::value_type value_type;
  1225. typedef typename container_type::const_reference reference;
  1226. typedef indexed_iterator2<container_type, iterator_category> iterator_type;
  1227. typedef indexed_const_iterator1<container_type, iterator_category> dual_iterator_type;
  1228. typedef reverse_iterator_base1<dual_iterator_type> dual_reverse_iterator_type;
  1229. // Construction and destruction
  1230. BOOST_UBLAS_INLINE
  1231. indexed_const_iterator2 ():
  1232. container_const_reference<container_type> (), it1_ (), it2_ () {}
  1233. BOOST_UBLAS_INLINE
  1234. indexed_const_iterator2 (const container_type &c, size_type it1, size_type it2):
  1235. container_const_reference<container_type> (c), it1_ (it1), it2_ (it2) {}
  1236. BOOST_UBLAS_INLINE
  1237. indexed_const_iterator2 (const iterator_type &it):
  1238. container_const_reference<container_type> (it ()), it1_ (it.index1 ()), it2_ (it.index2 ()) {}
  1239. // Arithmetic
  1240. BOOST_UBLAS_INLINE
  1241. indexed_const_iterator2 &operator ++ () {
  1242. ++ it2_;
  1243. return *this;
  1244. }
  1245. BOOST_UBLAS_INLINE
  1246. indexed_const_iterator2 &operator -- () {
  1247. -- it2_;
  1248. return *this;
  1249. }
  1250. BOOST_UBLAS_INLINE
  1251. indexed_const_iterator2 &operator += (difference_type n) {
  1252. it2_ += n;
  1253. return *this;
  1254. }
  1255. BOOST_UBLAS_INLINE
  1256. indexed_const_iterator2 &operator -= (difference_type n) {
  1257. it2_ -= n;
  1258. return *this;
  1259. }
  1260. BOOST_UBLAS_INLINE
  1261. difference_type operator - (const indexed_const_iterator2 &it) const {
  1262. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1263. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  1264. return it2_ - it.it2_;
  1265. }
  1266. // Dereference
  1267. BOOST_UBLAS_INLINE
  1268. reference operator * () const {
  1269. BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  1270. BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  1271. return (*this) () (it1_, it2_);
  1272. }
  1273. BOOST_UBLAS_INLINE
  1274. reference operator [] (difference_type n) const {
  1275. return *((*this) + n);
  1276. }
  1277. // Index
  1278. BOOST_UBLAS_INLINE
  1279. size_type index1 () const {
  1280. return it1_;
  1281. }
  1282. BOOST_UBLAS_INLINE
  1283. size_type index2 () const {
  1284. return it2_;
  1285. }
  1286. BOOST_UBLAS_INLINE
  1287. dual_iterator_type begin () const {
  1288. return (*this) ().find1 (1, 0, index2 ());
  1289. }
  1290. BOOST_UBLAS_INLINE
  1291. dual_iterator_type end () const {
  1292. return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
  1293. }
  1294. BOOST_UBLAS_INLINE
  1295. dual_reverse_iterator_type rbegin () const {
  1296. return dual_reverse_iterator_type (end ());
  1297. }
  1298. BOOST_UBLAS_INLINE
  1299. dual_reverse_iterator_type rend () const {
  1300. return dual_reverse_iterator_type (begin ());
  1301. }
  1302. // Assignment
  1303. BOOST_UBLAS_INLINE
  1304. indexed_const_iterator2 &operator = (const indexed_const_iterator2 &it) {
  1305. // FIX: ICC needs full qualification?!
  1306. // assign (&it ());
  1307. container_const_reference<C>::assign (&it ());
  1308. it1_ = it.it1_;
  1309. it2_ = it.it2_;
  1310. return *this;
  1311. }
  1312. // Comparison
  1313. BOOST_UBLAS_INLINE
  1314. bool operator == (const indexed_const_iterator2 &it) const {
  1315. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1316. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  1317. return it2_ == it.it2_;
  1318. }
  1319. BOOST_UBLAS_INLINE
  1320. bool operator < (const indexed_const_iterator2 &it) const {
  1321. BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1322. BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  1323. return it2_ < it.it2_;
  1324. }
  1325. private:
  1326. size_type it1_;
  1327. size_type it2_;
  1328. friend class indexed_iterator2<container_type, iterator_category>;
  1329. };
  1330. }}}
  1331. #endif