vector_proxy.hpp 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697
  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_VECTOR_PROXY_
  13. #define _BOOST_UBLAS_VECTOR_PROXY_
  14. #include <boost/numeric/ublas/vector_expression.hpp>
  15. #include <boost/numeric/ublas/detail/vector_assign.hpp>
  16. #include <boost/numeric/ublas/detail/temporary.hpp>
  17. // Iterators based on ideas of Jeremy Siek
  18. namespace boost { namespace numeric { namespace ublas {
  19. /** \brief A vector referencing a continuous subvector of elements of vector \c v containing all elements specified by \c range.
  20. *
  21. * A vector range can be used as a normal vector in any expression.
  22. * If the specified range falls outside that of the index range of the vector, then
  23. * the \c vector_range is not a well formed \i Vector \i Expression and access to an
  24. * element outside of index range of the vector is \b undefined.
  25. *
  26. * \tparam V the type of vector referenced (for example \c vector<double>)
  27. */
  28. template<class V>
  29. class vector_range:
  30. public vector_expression<vector_range<V> > {
  31. typedef vector_range<V> self_type;
  32. public:
  33. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  34. using vector_expression<self_type>::operator ();
  35. #endif
  36. typedef const V const_vector_type;
  37. typedef V vector_type;
  38. typedef typename V::size_type size_type;
  39. typedef typename V::difference_type difference_type;
  40. typedef typename V::value_type value_type;
  41. typedef typename V::const_reference const_reference;
  42. typedef typename boost::mpl::if_<boost::is_const<V>,
  43. typename V::const_reference,
  44. typename V::reference>::type reference;
  45. typedef typename boost::mpl::if_<boost::is_const<V>,
  46. typename V::const_closure_type,
  47. typename V::closure_type>::type vector_closure_type;
  48. typedef basic_range<size_type, difference_type> range_type;
  49. typedef const self_type const_closure_type;
  50. typedef self_type closure_type;
  51. typedef typename storage_restrict_traits<typename V::storage_category,
  52. dense_proxy_tag>::storage_category storage_category;
  53. // Construction and destruction
  54. BOOST_UBLAS_INLINE
  55. vector_range (vector_type &data, const range_type &r):
  56. data_ (data), r_ (r.preprocess (data.size ())) {
  57. // Early checking of preconditions here.
  58. // BOOST_UBLAS_CHECK (r_.start () <= data_.size () &&
  59. // r_.start () + r_.size () <= data_.size (), bad_index ());
  60. }
  61. BOOST_UBLAS_INLINE
  62. vector_range (const vector_closure_type &data, const range_type &r, bool):
  63. data_ (data), r_ (r.preprocess (data.size ())) {
  64. // Early checking of preconditions here.
  65. // BOOST_UBLAS_CHECK (r_.start () <= data_.size () &&
  66. // r_.start () + r_.size () <= data_.size (), bad_index ());
  67. }
  68. // Accessors
  69. BOOST_UBLAS_INLINE
  70. size_type start () const {
  71. return r_.start ();
  72. }
  73. BOOST_UBLAS_INLINE
  74. size_type size () const {
  75. return r_.size ();
  76. }
  77. // Storage accessors
  78. BOOST_UBLAS_INLINE
  79. const vector_closure_type &data () const {
  80. return data_;
  81. }
  82. BOOST_UBLAS_INLINE
  83. vector_closure_type &data () {
  84. return data_;
  85. }
  86. // Element access
  87. #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
  88. BOOST_UBLAS_INLINE
  89. const_reference operator () (size_type i) const {
  90. return data_ (r_ (i));
  91. }
  92. BOOST_UBLAS_INLINE
  93. reference operator () (size_type i) {
  94. return data_ (r_ (i));
  95. }
  96. BOOST_UBLAS_INLINE
  97. const_reference operator [] (size_type i) const {
  98. return (*this) (i);
  99. }
  100. BOOST_UBLAS_INLINE
  101. reference operator [] (size_type i) {
  102. return (*this) (i);
  103. }
  104. #else
  105. BOOST_UBLAS_INLINE
  106. reference operator () (size_type i) const {
  107. return data_ (r_ (i));
  108. }
  109. BOOST_UBLAS_INLINE
  110. reference operator [] (size_type i) const {
  111. return (*this) (i);
  112. }
  113. #endif
  114. // ISSUE can this be done in free project function?
  115. // Although a const function can create a non-const proxy to a non-const object
  116. // Critical is that vector_type and data_ (vector_closure_type) are const correct
  117. BOOST_UBLAS_INLINE
  118. vector_range<vector_type> project (const range_type &r) const {
  119. return vector_range<vector_type> (data_, r_.compose (r.preprocess (data_.size ())), false);
  120. }
  121. // Assignment
  122. BOOST_UBLAS_INLINE
  123. vector_range &operator = (const vector_range &vr) {
  124. // ISSUE need a temporary, proxy can be overlaping alias
  125. vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vr));
  126. return *this;
  127. }
  128. BOOST_UBLAS_INLINE
  129. vector_range &assign_temporary (vector_range &vr) {
  130. // assign elements, proxied container remains the same
  131. vector_assign<scalar_assign> (*this, vr);
  132. return *this;
  133. }
  134. template<class AE>
  135. BOOST_UBLAS_INLINE
  136. vector_range &operator = (const vector_expression<AE> &ae) {
  137. vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
  138. return *this;
  139. }
  140. template<class AE>
  141. BOOST_UBLAS_INLINE
  142. vector_range &assign (const vector_expression<AE> &ae) {
  143. vector_assign<scalar_assign> (*this, ae);
  144. return *this;
  145. }
  146. template<class AE>
  147. BOOST_UBLAS_INLINE
  148. vector_range &operator += (const vector_expression<AE> &ae) {
  149. vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
  150. return *this;
  151. }
  152. template<class AE>
  153. BOOST_UBLAS_INLINE
  154. vector_range &plus_assign (const vector_expression<AE> &ae) {
  155. vector_assign<scalar_plus_assign> (*this, ae);
  156. return *this;
  157. }
  158. template<class AE>
  159. BOOST_UBLAS_INLINE
  160. vector_range &operator -= (const vector_expression<AE> &ae) {
  161. vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
  162. return *this;
  163. }
  164. template<class AE>
  165. BOOST_UBLAS_INLINE
  166. vector_range &minus_assign (const vector_expression<AE> &ae) {
  167. vector_assign<scalar_minus_assign> (*this, ae);
  168. return *this;
  169. }
  170. template<class AT>
  171. BOOST_UBLAS_INLINE
  172. vector_range &operator *= (const AT &at) {
  173. vector_assign_scalar<scalar_multiplies_assign> (*this, at);
  174. return *this;
  175. }
  176. template<class AT>
  177. BOOST_UBLAS_INLINE
  178. vector_range &operator /= (const AT &at) {
  179. vector_assign_scalar<scalar_divides_assign> (*this, at);
  180. return *this;
  181. }
  182. // Closure comparison
  183. BOOST_UBLAS_INLINE
  184. bool same_closure (const vector_range &vr) const {
  185. return (*this).data_.same_closure (vr.data_);
  186. }
  187. // Comparison
  188. BOOST_UBLAS_INLINE
  189. bool operator == (const vector_range &vr) const {
  190. return (*this).data_ == vr.data_ && r_ == vr.r_;
  191. }
  192. // Swapping
  193. BOOST_UBLAS_INLINE
  194. void swap (vector_range vr) {
  195. if (this != &vr) {
  196. BOOST_UBLAS_CHECK (size () == vr.size (), bad_size ());
  197. // Sparse ranges may be nonconformant now.
  198. // std::swap_ranges (begin (), end (), vr.begin ());
  199. vector_swap<scalar_swap> (*this, vr);
  200. }
  201. }
  202. BOOST_UBLAS_INLINE
  203. friend void swap (vector_range vr1, vector_range vr2) {
  204. vr1.swap (vr2);
  205. }
  206. // Iterator types
  207. private:
  208. typedef typename V::const_iterator const_subiterator_type;
  209. typedef typename boost::mpl::if_<boost::is_const<V>,
  210. typename V::const_iterator,
  211. typename V::iterator>::type subiterator_type;
  212. public:
  213. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  214. typedef indexed_iterator<vector_range<vector_type>,
  215. typename subiterator_type::iterator_category> iterator;
  216. typedef indexed_const_iterator<vector_range<vector_type>,
  217. typename const_subiterator_type::iterator_category> const_iterator;
  218. #else
  219. class const_iterator;
  220. class iterator;
  221. #endif
  222. // Element lookup
  223. BOOST_UBLAS_INLINE
  224. const_iterator find (size_type i) const {
  225. const_subiterator_type it (data_.find (start () + i));
  226. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  227. return const_iterator (*this, it.index ());
  228. #else
  229. return const_iterator (*this, it);
  230. #endif
  231. }
  232. BOOST_UBLAS_INLINE
  233. iterator find (size_type i) {
  234. subiterator_type it (data_.find (start () + i));
  235. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  236. return iterator (*this, it.index ());
  237. #else
  238. return iterator (*this, it);
  239. #endif
  240. }
  241. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  242. class const_iterator:
  243. public container_const_reference<vector_range>,
  244. public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
  245. iterator_base<const_iterator, value_type>::type {
  246. public:
  247. typedef typename const_subiterator_type::difference_type difference_type;
  248. typedef typename const_subiterator_type::value_type value_type;
  249. typedef typename const_subiterator_type::reference reference;
  250. typedef typename const_subiterator_type::pointer pointer;
  251. // Construction and destruction
  252. BOOST_UBLAS_INLINE
  253. const_iterator ():
  254. container_const_reference<self_type> (), it_ () {}
  255. BOOST_UBLAS_INLINE
  256. const_iterator (const self_type &vr, const const_subiterator_type &it):
  257. container_const_reference<self_type> (vr), it_ (it) {}
  258. BOOST_UBLAS_INLINE
  259. const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
  260. container_const_reference<self_type> (it ()), it_ (it.it_) {}
  261. // Arithmetic
  262. BOOST_UBLAS_INLINE
  263. const_iterator &operator ++ () {
  264. ++ it_;
  265. return *this;
  266. }
  267. BOOST_UBLAS_INLINE
  268. const_iterator &operator -- () {
  269. -- it_;
  270. return *this;
  271. }
  272. BOOST_UBLAS_INLINE
  273. const_iterator &operator += (difference_type n) {
  274. it_ += n;
  275. return *this;
  276. }
  277. BOOST_UBLAS_INLINE
  278. const_iterator &operator -= (difference_type n) {
  279. it_ -= n;
  280. return *this;
  281. }
  282. BOOST_UBLAS_INLINE
  283. difference_type operator - (const const_iterator &it) const {
  284. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  285. return it_ - it.it_;
  286. }
  287. // Dereference
  288. BOOST_UBLAS_INLINE
  289. const_reference operator * () const {
  290. BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
  291. return *it_;
  292. }
  293. BOOST_UBLAS_INLINE
  294. const_reference operator [] (difference_type n) const {
  295. return *(*this + n);
  296. }
  297. // Index
  298. BOOST_UBLAS_INLINE
  299. size_type index () const {
  300. return it_.index () - (*this) ().start ();
  301. }
  302. // Assignment
  303. BOOST_UBLAS_INLINE
  304. const_iterator &operator = (const const_iterator &it) {
  305. container_const_reference<self_type>::assign (&it ());
  306. it_ = it.it_;
  307. return *this;
  308. }
  309. // Comparison
  310. BOOST_UBLAS_INLINE
  311. bool operator == (const const_iterator &it) const {
  312. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  313. return it_ == it.it_;
  314. }
  315. BOOST_UBLAS_INLINE
  316. bool operator < (const const_iterator &it) const {
  317. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  318. return it_ < it.it_;
  319. }
  320. private:
  321. const_subiterator_type it_;
  322. };
  323. #endif
  324. BOOST_UBLAS_INLINE
  325. const_iterator begin () const {
  326. return find (0);
  327. }
  328. BOOST_UBLAS_INLINE
  329. const_iterator cbegin () const {
  330. return begin ();
  331. }
  332. BOOST_UBLAS_INLINE
  333. const_iterator end () const {
  334. return find (size ());
  335. }
  336. BOOST_UBLAS_INLINE
  337. const_iterator cend () const {
  338. return end ();
  339. }
  340. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  341. class iterator:
  342. public container_reference<vector_range>,
  343. public iterator_base_traits<typename subiterator_type::iterator_category>::template
  344. iterator_base<iterator, value_type>::type {
  345. public:
  346. typedef typename subiterator_type::difference_type difference_type;
  347. typedef typename subiterator_type::value_type value_type;
  348. typedef typename subiterator_type::reference reference;
  349. typedef typename subiterator_type::pointer pointer;
  350. // Construction and destruction
  351. BOOST_UBLAS_INLINE
  352. iterator ():
  353. container_reference<self_type> (), it_ () {}
  354. BOOST_UBLAS_INLINE
  355. iterator (self_type &vr, const subiterator_type &it):
  356. container_reference<self_type> (vr), it_ (it) {}
  357. // Arithmetic
  358. BOOST_UBLAS_INLINE
  359. iterator &operator ++ () {
  360. ++ it_;
  361. return *this;
  362. }
  363. BOOST_UBLAS_INLINE
  364. iterator &operator -- () {
  365. -- it_;
  366. return *this;
  367. }
  368. BOOST_UBLAS_INLINE
  369. iterator &operator += (difference_type n) {
  370. it_ += n;
  371. return *this;
  372. }
  373. BOOST_UBLAS_INLINE
  374. iterator &operator -= (difference_type n) {
  375. it_ -= n;
  376. return *this;
  377. }
  378. BOOST_UBLAS_INLINE
  379. difference_type operator - (const iterator &it) const {
  380. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  381. return it_ - it.it_;
  382. }
  383. // Dereference
  384. BOOST_UBLAS_INLINE
  385. reference operator * () const {
  386. BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
  387. return *it_;
  388. }
  389. BOOST_UBLAS_INLINE
  390. reference operator [] (difference_type n) const {
  391. return *(*this + n);
  392. }
  393. // Index
  394. BOOST_UBLAS_INLINE
  395. size_type index () const {
  396. return it_.index () - (*this) ().start ();
  397. }
  398. // Assignment
  399. BOOST_UBLAS_INLINE
  400. iterator &operator = (const iterator &it) {
  401. container_reference<self_type>::assign (&it ());
  402. it_ = it.it_;
  403. return *this;
  404. }
  405. // Comparison
  406. BOOST_UBLAS_INLINE
  407. bool operator == (const iterator &it) const {
  408. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  409. return it_ == it.it_;
  410. }
  411. BOOST_UBLAS_INLINE
  412. bool operator < (const iterator &it) const {
  413. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  414. return it_ < it.it_;
  415. }
  416. private:
  417. subiterator_type it_;
  418. friend class const_iterator;
  419. };
  420. #endif
  421. BOOST_UBLAS_INLINE
  422. iterator begin () {
  423. return find (0);
  424. }
  425. BOOST_UBLAS_INLINE
  426. iterator end () {
  427. return find (size ());
  428. }
  429. // Reverse iterator
  430. typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
  431. typedef reverse_iterator_base<iterator> reverse_iterator;
  432. BOOST_UBLAS_INLINE
  433. const_reverse_iterator rbegin () const {
  434. return const_reverse_iterator (end ());
  435. }
  436. BOOST_UBLAS_INLINE
  437. const_reverse_iterator crbegin () const {
  438. return rbegin ();
  439. }
  440. BOOST_UBLAS_INLINE
  441. const_reverse_iterator rend () const {
  442. return const_reverse_iterator (begin ());
  443. }
  444. BOOST_UBLAS_INLINE
  445. const_reverse_iterator crend () const {
  446. return rend ();
  447. }
  448. BOOST_UBLAS_INLINE
  449. reverse_iterator rbegin () {
  450. return reverse_iterator (end ());
  451. }
  452. BOOST_UBLAS_INLINE
  453. reverse_iterator rend () {
  454. return reverse_iterator (begin ());
  455. }
  456. private:
  457. vector_closure_type data_;
  458. range_type r_;
  459. };
  460. // ------------------
  461. // Simple Projections
  462. // ------------------
  463. /** \brief Return a \c vector_range on a specified vector, a start and stop index.
  464. * Return a \c vector_range on a specified vector, a start and stop index. The resulting \c vector_range can be manipulated like a normal vector.
  465. * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
  466. * Vector Expression and access to an element outside of index range of the vector is \b undefined.
  467. */
  468. template<class V>
  469. BOOST_UBLAS_INLINE
  470. vector_range<V> subrange (V &data, typename V::size_type start, typename V::size_type stop) {
  471. typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
  472. return vector_range<V> (data, range_type (start, stop));
  473. }
  474. /** \brief Return a \c const \c vector_range on a specified vector, a start and stop index.
  475. * Return a \c const \c vector_range on a specified vector, a start and stop index. The resulting \c const \c vector_range can be manipulated like a normal vector.
  476. *If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
  477. * Vector Expression and access to an element outside of index range of the vector is \b undefined.
  478. */
  479. template<class V>
  480. BOOST_UBLAS_INLINE
  481. vector_range<const V> subrange (const V &data, typename V::size_type start, typename V::size_type stop) {
  482. typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
  483. return vector_range<const V> (data, range_type (start, stop));
  484. }
  485. // -------------------
  486. // Generic Projections
  487. // -------------------
  488. /** \brief Return a \c const \c vector_range on a specified vector and \c range
  489. * Return a \c const \c vector_range on a specified vector and \c range. The resulting \c vector_range can be manipulated like a normal vector.
  490. * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
  491. * Vector Expression and access to an element outside of index range of the vector is \b undefined.
  492. */
  493. template<class V>
  494. BOOST_UBLAS_INLINE
  495. vector_range<V> project (V &data, typename vector_range<V>::range_type const &r) {
  496. return vector_range<V> (data, r);
  497. }
  498. /** \brief Return a \c vector_range on a specified vector and \c range
  499. * Return a \c vector_range on a specified vector and \c range. The resulting \c vector_range can be manipulated like a normal vector.
  500. * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
  501. * Vector Expression and access to an element outside of index range of the vector is \b undefined.
  502. */
  503. template<class V>
  504. BOOST_UBLAS_INLINE
  505. const vector_range<const V> project (const V &data, typename vector_range<V>::range_type const &r) {
  506. // ISSUE was: return vector_range<V> (const_cast<V &> (data), r);
  507. return vector_range<const V> (data, r);
  508. }
  509. /** \brief Return a \c const \c vector_range on a specified vector and const \c range
  510. * Return a \c const \c vector_range on a specified vector and const \c range. The resulting \c vector_range can be manipulated like a normal vector.
  511. * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
  512. * Vector Expression and access to an element outside of index range of the vector is \b undefined.
  513. */
  514. template<class V>
  515. BOOST_UBLAS_INLINE
  516. vector_range<V> project (vector_range<V> &data, const typename vector_range<V>::range_type &r) {
  517. return data.project (r);
  518. }
  519. /** \brief Return a \c vector_range on a specified vector and const \c range
  520. * Return a \c vector_range on a specified vector and const \c range. The resulting \c vector_range can be manipulated like a normal vector.
  521. * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
  522. * Vector Expression and access to an element outside of index range of the vector is \b undefined.
  523. */
  524. template<class V>
  525. BOOST_UBLAS_INLINE
  526. const vector_range<V> project (const vector_range<V> &data, const typename vector_range<V>::range_type &r) {
  527. return data.project (r);
  528. }
  529. // Specialization of temporary_traits
  530. template <class V>
  531. struct vector_temporary_traits< vector_range<V> >
  532. : vector_temporary_traits< V > {} ;
  533. template <class V>
  534. struct vector_temporary_traits< const vector_range<V> >
  535. : vector_temporary_traits< V > {} ;
  536. /** \brief A vector referencing a non continuous subvector of elements of vector v containing all elements specified by \c slice.
  537. *
  538. * A vector slice can be used as a normal vector in any expression.
  539. * If the specified slice falls outside that of the index slice of the vector, then
  540. * the \c vector_slice is not a well formed \i Vector \i Expression and access to an
  541. * element outside of index slice of the vector is \b undefined.
  542. *
  543. * A slice is a generalization of a range. In a range going from \f$a\f$ to \f$b\f$,
  544. * all elements belong to the range. In a slice, a \i \f$step\f$ can be specified meaning to
  545. * take one element over \f$step\f$ in the range specified from \f$a\f$ to \f$b\f$.
  546. * Obviously, a slice with a \f$step\f$ of 1 is equivalent to a range.
  547. *
  548. * \tparam V the type of vector referenced (for example \c vector<double>)
  549. */
  550. template<class V>
  551. class vector_slice:
  552. public vector_expression<vector_slice<V> > {
  553. typedef vector_slice<V> self_type;
  554. public:
  555. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  556. using vector_expression<self_type>::operator ();
  557. #endif
  558. typedef const V const_vector_type;
  559. typedef V vector_type;
  560. typedef typename V::size_type size_type;
  561. typedef typename V::difference_type difference_type;
  562. typedef typename V::value_type value_type;
  563. typedef typename V::const_reference const_reference;
  564. typedef typename boost::mpl::if_<boost::is_const<V>,
  565. typename V::const_reference,
  566. typename V::reference>::type reference;
  567. typedef typename boost::mpl::if_<boost::is_const<V>,
  568. typename V::const_closure_type,
  569. typename V::closure_type>::type vector_closure_type;
  570. typedef basic_range<size_type, difference_type> range_type;
  571. typedef basic_slice<size_type, difference_type> slice_type;
  572. typedef const self_type const_closure_type;
  573. typedef self_type closure_type;
  574. typedef typename storage_restrict_traits<typename V::storage_category,
  575. dense_proxy_tag>::storage_category storage_category;
  576. // Construction and destruction
  577. BOOST_UBLAS_INLINE
  578. vector_slice (vector_type &data, const slice_type &s):
  579. data_ (data), s_ (s.preprocess (data.size ())) {
  580. // Early checking of preconditions here.
  581. // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
  582. // s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
  583. }
  584. BOOST_UBLAS_INLINE
  585. vector_slice (const vector_closure_type &data, const slice_type &s, int):
  586. data_ (data), s_ (s.preprocess (data.size ())) {
  587. // Early checking of preconditions here.
  588. // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
  589. // s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
  590. }
  591. // Accessors
  592. BOOST_UBLAS_INLINE
  593. size_type start () const {
  594. return s_.start ();
  595. }
  596. BOOST_UBLAS_INLINE
  597. difference_type stride () const {
  598. return s_.stride ();
  599. }
  600. BOOST_UBLAS_INLINE
  601. size_type size () const {
  602. return s_.size ();
  603. }
  604. // Storage accessors
  605. BOOST_UBLAS_INLINE
  606. const vector_closure_type &data () const {
  607. return data_;
  608. }
  609. BOOST_UBLAS_INLINE
  610. vector_closure_type &data () {
  611. return data_;
  612. }
  613. // Element access
  614. #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
  615. BOOST_UBLAS_INLINE
  616. const_reference operator () (size_type i) const {
  617. return data_ (s_ (i));
  618. }
  619. BOOST_UBLAS_INLINE
  620. reference operator () (size_type i) {
  621. return data_ (s_ (i));
  622. }
  623. BOOST_UBLAS_INLINE
  624. const_reference operator [] (size_type i) const {
  625. return (*this) (i);
  626. }
  627. BOOST_UBLAS_INLINE
  628. reference operator [] (size_type i) {
  629. return (*this) (i);
  630. }
  631. #else
  632. BOOST_UBLAS_INLINE
  633. reference operator () (size_type i) const {
  634. return data_ (s_ (i));
  635. }
  636. BOOST_UBLAS_INLINE
  637. reference operator [] (size_type i) const {
  638. return (*this) (i);
  639. }
  640. #endif
  641. // ISSUE can this be done in free project function?
  642. // Although a const function can create a non-const proxy to a non-const object
  643. // Critical is that vector_type and data_ (vector_closure_type) are const correct
  644. BOOST_UBLAS_INLINE
  645. vector_slice<vector_type> project (const range_type &r) const {
  646. return vector_slice<vector_type> (data_, s_.compose (r.preprocess (data_.size ())), false);
  647. }
  648. BOOST_UBLAS_INLINE
  649. vector_slice<vector_type> project (const slice_type &s) const {
  650. return vector_slice<vector_type> (data_, s_.compose (s.preprocess (data_.size ())), false);
  651. }
  652. // Assignment
  653. BOOST_UBLAS_INLINE
  654. vector_slice &operator = (const vector_slice &vs) {
  655. // ISSUE need a temporary, proxy can be overlaping alias
  656. vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vs));
  657. return *this;
  658. }
  659. BOOST_UBLAS_INLINE
  660. vector_slice &assign_temporary (vector_slice &vs) {
  661. // assign elements, proxied container remains the same
  662. vector_assign<scalar_assign> (*this, vs);
  663. return *this;
  664. }
  665. template<class AE>
  666. BOOST_UBLAS_INLINE
  667. vector_slice &operator = (const vector_expression<AE> &ae) {
  668. vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
  669. return *this;
  670. }
  671. template<class AE>
  672. BOOST_UBLAS_INLINE
  673. vector_slice &assign (const vector_expression<AE> &ae) {
  674. vector_assign<scalar_assign> (*this, ae);
  675. return *this;
  676. }
  677. template<class AE>
  678. BOOST_UBLAS_INLINE
  679. vector_slice &operator += (const vector_expression<AE> &ae) {
  680. vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
  681. return *this;
  682. }
  683. template<class AE>
  684. BOOST_UBLAS_INLINE
  685. vector_slice &plus_assign (const vector_expression<AE> &ae) {
  686. vector_assign<scalar_plus_assign> (*this, ae);
  687. return *this;
  688. }
  689. template<class AE>
  690. BOOST_UBLAS_INLINE
  691. vector_slice &operator -= (const vector_expression<AE> &ae) {
  692. vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
  693. return *this;
  694. }
  695. template<class AE>
  696. BOOST_UBLAS_INLINE
  697. vector_slice &minus_assign (const vector_expression<AE> &ae) {
  698. vector_assign<scalar_minus_assign> (*this, ae);
  699. return *this;
  700. }
  701. template<class AT>
  702. BOOST_UBLAS_INLINE
  703. vector_slice &operator *= (const AT &at) {
  704. vector_assign_scalar<scalar_multiplies_assign> (*this, at);
  705. return *this;
  706. }
  707. template<class AT>
  708. BOOST_UBLAS_INLINE
  709. vector_slice &operator /= (const AT &at) {
  710. vector_assign_scalar<scalar_divides_assign> (*this, at);
  711. return *this;
  712. }
  713. // Closure comparison
  714. BOOST_UBLAS_INLINE
  715. bool same_closure (const vector_slice &vr) const {
  716. return (*this).data_.same_closure (vr.data_);
  717. }
  718. // Comparison
  719. BOOST_UBLAS_INLINE
  720. bool operator == (const vector_slice &vs) const {
  721. return (*this).data_ == vs.data_ && s_ == vs.s_;
  722. }
  723. // Swapping
  724. BOOST_UBLAS_INLINE
  725. void swap (vector_slice vs) {
  726. if (this != &vs) {
  727. BOOST_UBLAS_CHECK (size () == vs.size (), bad_size ());
  728. // Sparse ranges may be nonconformant now.
  729. // std::swap_ranges (begin (), end (), vs.begin ());
  730. vector_swap<scalar_swap> (*this, vs);
  731. }
  732. }
  733. BOOST_UBLAS_INLINE
  734. friend void swap (vector_slice vs1, vector_slice vs2) {
  735. vs1.swap (vs2);
  736. }
  737. // Iterator types
  738. private:
  739. // Use slice as an index - FIXME this fails for packed assignment
  740. typedef typename slice_type::const_iterator const_subiterator_type;
  741. typedef typename slice_type::const_iterator subiterator_type;
  742. public:
  743. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  744. typedef indexed_iterator<vector_slice<vector_type>,
  745. typename vector_type::iterator::iterator_category> iterator;
  746. typedef indexed_const_iterator<vector_slice<vector_type>,
  747. typename vector_type::const_iterator::iterator_category> const_iterator;
  748. #else
  749. class const_iterator;
  750. class iterator;
  751. #endif
  752. // Element lookup
  753. BOOST_UBLAS_INLINE
  754. const_iterator find (size_type i) const {
  755. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  756. return const_iterator (*this, i);
  757. #else
  758. return const_iterator (*this, s_.begin () + i);
  759. #endif
  760. }
  761. BOOST_UBLAS_INLINE
  762. iterator find (size_type i) {
  763. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  764. return iterator (*this, i);
  765. #else
  766. return iterator (*this, s_.begin () + i);
  767. #endif
  768. }
  769. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  770. class const_iterator:
  771. public container_const_reference<vector_slice>,
  772. public iterator_base_traits<typename V::const_iterator::iterator_category>::template
  773. iterator_base<const_iterator, value_type>::type {
  774. public:
  775. typedef typename V::const_iterator::difference_type difference_type;
  776. typedef typename V::const_iterator::value_type value_type;
  777. typedef typename V::const_reference reference; //FIXME due to indexing access
  778. typedef typename V::const_iterator::pointer pointer;
  779. // Construction and destruction
  780. BOOST_UBLAS_INLINE
  781. const_iterator ():
  782. container_const_reference<self_type> (), it_ () {}
  783. BOOST_UBLAS_INLINE
  784. const_iterator (const self_type &vs, const const_subiterator_type &it):
  785. container_const_reference<self_type> (vs), it_ (it) {}
  786. BOOST_UBLAS_INLINE
  787. const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
  788. container_const_reference<self_type> (it ()), it_ (it.it_) {}
  789. // Arithmetic
  790. BOOST_UBLAS_INLINE
  791. const_iterator &operator ++ () {
  792. ++ it_;
  793. return *this;
  794. }
  795. BOOST_UBLAS_INLINE
  796. const_iterator &operator -- () {
  797. -- it_;
  798. return *this;
  799. }
  800. BOOST_UBLAS_INLINE
  801. const_iterator &operator += (difference_type n) {
  802. it_ += n;
  803. return *this;
  804. }
  805. BOOST_UBLAS_INLINE
  806. const_iterator &operator -= (difference_type n) {
  807. it_ -= n;
  808. return *this;
  809. }
  810. BOOST_UBLAS_INLINE
  811. difference_type operator - (const const_iterator &it) const {
  812. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  813. return it_ - it.it_;
  814. }
  815. // Dereference
  816. BOOST_UBLAS_INLINE
  817. const_reference operator * () const {
  818. // FIXME replace find with at_element
  819. BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
  820. return (*this) ().data_ (*it_);
  821. }
  822. BOOST_UBLAS_INLINE
  823. const_reference operator [] (difference_type n) const {
  824. return *(*this + n);
  825. }
  826. // Index
  827. BOOST_UBLAS_INLINE
  828. size_type index () const {
  829. return it_.index ();
  830. }
  831. // Assignment
  832. BOOST_UBLAS_INLINE
  833. const_iterator &operator = (const const_iterator &it) {
  834. container_const_reference<self_type>::assign (&it ());
  835. it_ = it.it_;
  836. return *this;
  837. }
  838. // Comparison
  839. BOOST_UBLAS_INLINE
  840. bool operator == (const const_iterator &it) const {
  841. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  842. return it_ == it.it_;
  843. }
  844. BOOST_UBLAS_INLINE
  845. bool operator < (const const_iterator &it) const {
  846. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  847. return it_ < it.it_;
  848. }
  849. private:
  850. const_subiterator_type it_;
  851. };
  852. #endif
  853. BOOST_UBLAS_INLINE
  854. const_iterator begin () const {
  855. return find (0);
  856. }
  857. BOOST_UBLAS_INLINE
  858. const_iterator cbegin () const {
  859. return begin ();
  860. }
  861. BOOST_UBLAS_INLINE
  862. const_iterator end () const {
  863. return find (size ());
  864. }
  865. BOOST_UBLAS_INLINE
  866. const_iterator cend () const {
  867. return end ();
  868. }
  869. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  870. class iterator:
  871. public container_reference<vector_slice>,
  872. public iterator_base_traits<typename V::iterator::iterator_category>::template
  873. iterator_base<iterator, value_type>::type {
  874. public:
  875. typedef typename V::iterator::difference_type difference_type;
  876. typedef typename V::iterator::value_type value_type;
  877. typedef typename V::reference reference; //FIXME due to indexing access
  878. typedef typename V::iterator::pointer pointer;
  879. // Construction and destruction
  880. BOOST_UBLAS_INLINE
  881. iterator ():
  882. container_reference<self_type> (), it_ () {}
  883. BOOST_UBLAS_INLINE
  884. iterator (self_type &vs, const subiterator_type &it):
  885. container_reference<self_type> (vs), it_ (it) {}
  886. // Arithmetic
  887. BOOST_UBLAS_INLINE
  888. iterator &operator ++ () {
  889. ++ it_;
  890. return *this;
  891. }
  892. BOOST_UBLAS_INLINE
  893. iterator &operator -- () {
  894. -- it_;
  895. return *this;
  896. }
  897. BOOST_UBLAS_INLINE
  898. iterator &operator += (difference_type n) {
  899. it_ += n;
  900. return *this;
  901. }
  902. BOOST_UBLAS_INLINE
  903. iterator &operator -= (difference_type n) {
  904. it_ -= n;
  905. return *this;
  906. }
  907. BOOST_UBLAS_INLINE
  908. difference_type operator - (const iterator &it) const {
  909. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  910. return it_ - it.it_;
  911. }
  912. // Dereference
  913. BOOST_UBLAS_INLINE
  914. reference operator * () const {
  915. // FIXME replace find with at_element
  916. BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
  917. return (*this) ().data_ (*it_);
  918. }
  919. BOOST_UBLAS_INLINE
  920. reference operator [] (difference_type n) const {
  921. return *(*this + n);
  922. }
  923. // Index
  924. BOOST_UBLAS_INLINE
  925. size_type index () const {
  926. return it_.index ();
  927. }
  928. // Assignment
  929. BOOST_UBLAS_INLINE
  930. iterator &operator = (const iterator &it) {
  931. container_reference<self_type>::assign (&it ());
  932. it_ = it.it_;
  933. return *this;
  934. }
  935. // Comparison
  936. BOOST_UBLAS_INLINE
  937. bool operator == (const iterator &it) const {
  938. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  939. return it_ == it.it_;
  940. }
  941. BOOST_UBLAS_INLINE
  942. bool operator < (const iterator &it) const {
  943. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  944. return it_ < it.it_;
  945. }
  946. private:
  947. subiterator_type it_;
  948. friend class const_iterator;
  949. };
  950. #endif
  951. BOOST_UBLAS_INLINE
  952. iterator begin () {
  953. return find (0);
  954. }
  955. BOOST_UBLAS_INLINE
  956. iterator end () {
  957. return find (size ());
  958. }
  959. // Reverse iterator
  960. typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
  961. typedef reverse_iterator_base<iterator> reverse_iterator;
  962. BOOST_UBLAS_INLINE
  963. const_reverse_iterator rbegin () const {
  964. return const_reverse_iterator (end ());
  965. }
  966. BOOST_UBLAS_INLINE
  967. const_reverse_iterator crbegin () const {
  968. return rbegin ();
  969. }
  970. BOOST_UBLAS_INLINE
  971. const_reverse_iterator rend () const {
  972. return const_reverse_iterator (begin ());
  973. }
  974. BOOST_UBLAS_INLINE
  975. const_reverse_iterator crend () const {
  976. return rend ();
  977. }
  978. BOOST_UBLAS_INLINE
  979. reverse_iterator rbegin () {
  980. return reverse_iterator (end ());
  981. }
  982. BOOST_UBLAS_INLINE
  983. reverse_iterator rend () {
  984. return reverse_iterator (begin ());
  985. }
  986. private:
  987. vector_closure_type data_;
  988. slice_type s_;
  989. };
  990. // Simple Projections
  991. template<class V>
  992. BOOST_UBLAS_INLINE
  993. vector_slice<V> subslice (V &data, typename V::size_type start, typename V::difference_type stride, typename V::size_type size) {
  994. typedef basic_slice<typename V::size_type, typename V::difference_type> slice_type;
  995. return vector_slice<V> (data, slice_type (start, stride, size));
  996. }
  997. template<class V>
  998. BOOST_UBLAS_INLINE
  999. vector_slice<const V> subslice (const V &data, typename V::size_type start, typename V::difference_type stride, typename V::size_type size) {
  1000. typedef basic_slice<typename V::size_type, typename V::difference_type> slice_type;
  1001. return vector_slice<const V> (data, slice_type (start, stride, size));
  1002. }
  1003. // Generic Projections
  1004. template<class V>
  1005. BOOST_UBLAS_INLINE
  1006. vector_slice<V> project (V &data, const typename vector_slice<V>::slice_type &s) {
  1007. return vector_slice<V> (data, s);
  1008. }
  1009. template<class V>
  1010. BOOST_UBLAS_INLINE
  1011. const vector_slice<const V> project (const V &data, const typename vector_slice<V>::slice_type &s) {
  1012. // ISSUE was: return vector_slice<V> (const_cast<V &> (data), s);
  1013. return vector_slice<const V> (data, s);
  1014. }
  1015. template<class V>
  1016. BOOST_UBLAS_INLINE
  1017. vector_slice<V> project (vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
  1018. return data.project (s);
  1019. }
  1020. template<class V>
  1021. BOOST_UBLAS_INLINE
  1022. const vector_slice<V> project (const vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
  1023. return data.project (s);
  1024. }
  1025. // ISSUE in the following two functions it would be logical to use vector_slice<V>::range_type but this confuses VC7.1 and 8.0
  1026. template<class V>
  1027. BOOST_UBLAS_INLINE
  1028. vector_slice<V> project (vector_slice<V> &data, const typename vector_range<V>::range_type &r) {
  1029. return data.project (r);
  1030. }
  1031. template<class V>
  1032. BOOST_UBLAS_INLINE
  1033. const vector_slice<V> project (const vector_slice<V> &data, const typename vector_range<V>::range_type &r) {
  1034. return data.project (r);
  1035. }
  1036. // Specialization of temporary_traits
  1037. template <class V>
  1038. struct vector_temporary_traits< vector_slice<V> >
  1039. : vector_temporary_traits< V > {} ;
  1040. template <class V>
  1041. struct vector_temporary_traits< const vector_slice<V> >
  1042. : vector_temporary_traits< V > {} ;
  1043. // Vector based indirection class
  1044. // Contributed by Toon Knapen.
  1045. // Extended and optimized by Kresimir Fresl.
  1046. /** \brief A vector referencing a non continuous subvector of elements given another vector of indices.
  1047. *
  1048. * It is the most general version of any subvectors because it uses another vector of indices to reference
  1049. * the subvector.
  1050. *
  1051. * The vector of indices can be of any type with the restriction that its elements must be
  1052. * type-compatible with the size_type \c of the container. In practice, the following are good candidates:
  1053. * - \c boost::numeric::ublas::indirect_array<A> where \c A can be \c int, \c size_t, \c long, etc...
  1054. * - \c std::vector<A> where \c A can \c int, \c size_t, \c long, etc...
  1055. * - \c boost::numeric::ublas::vector<int> can work too (\c int can be replaced by another integer type)
  1056. * - etc...
  1057. *
  1058. * An indirect vector can be used as a normal vector in any expression. If the specified indirect vector
  1059. * falls outside that of the indices of the vector, then the \c vector_indirect is not a well formed
  1060. * \i Vector \i Expression and access to an element outside of indices of the vector is \b undefined.
  1061. *
  1062. * \tparam V the type of vector referenced (for example \c vector<double>)
  1063. * \tparam IA the type of index vector. Default is \c ublas::indirect_array<>
  1064. */
  1065. template<class V, class IA>
  1066. class vector_indirect:
  1067. public vector_expression<vector_indirect<V, IA> > {
  1068. typedef vector_indirect<V, IA> self_type;
  1069. public:
  1070. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  1071. using vector_expression<self_type>::operator ();
  1072. #endif
  1073. typedef const V const_vector_type;
  1074. typedef V vector_type;
  1075. typedef const IA const_indirect_array_type;
  1076. typedef IA indirect_array_type;
  1077. typedef typename V::size_type size_type;
  1078. typedef typename V::difference_type difference_type;
  1079. typedef typename V::value_type value_type;
  1080. typedef typename V::const_reference const_reference;
  1081. typedef typename boost::mpl::if_<boost::is_const<V>,
  1082. typename V::const_reference,
  1083. typename V::reference>::type reference;
  1084. typedef typename boost::mpl::if_<boost::is_const<V>,
  1085. typename V::const_closure_type,
  1086. typename V::closure_type>::type vector_closure_type;
  1087. typedef basic_range<size_type, difference_type> range_type;
  1088. typedef basic_slice<size_type, difference_type> slice_type;
  1089. typedef const self_type const_closure_type;
  1090. typedef self_type closure_type;
  1091. typedef typename storage_restrict_traits<typename V::storage_category,
  1092. dense_proxy_tag>::storage_category storage_category;
  1093. // Construction and destruction
  1094. BOOST_UBLAS_INLINE
  1095. vector_indirect (vector_type &data, size_type size):
  1096. data_ (data), ia_ (size) {}
  1097. BOOST_UBLAS_INLINE
  1098. vector_indirect (vector_type &data, const indirect_array_type &ia):
  1099. data_ (data), ia_ (ia.preprocess (data.size ())) {}
  1100. BOOST_UBLAS_INLINE
  1101. vector_indirect (const vector_closure_type &data, const indirect_array_type &ia, int):
  1102. data_ (data), ia_ (ia.preprocess (data.size ())) {}
  1103. // Accessors
  1104. BOOST_UBLAS_INLINE
  1105. size_type size () const {
  1106. return ia_.size ();
  1107. }
  1108. BOOST_UBLAS_INLINE
  1109. const_indirect_array_type &indirect () const {
  1110. return ia_;
  1111. }
  1112. BOOST_UBLAS_INLINE
  1113. indirect_array_type &indirect () {
  1114. return ia_;
  1115. }
  1116. // Storage accessors
  1117. BOOST_UBLAS_INLINE
  1118. const vector_closure_type &data () const {
  1119. return data_;
  1120. }
  1121. BOOST_UBLAS_INLINE
  1122. vector_closure_type &data () {
  1123. return data_;
  1124. }
  1125. // Element access
  1126. #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
  1127. BOOST_UBLAS_INLINE
  1128. const_reference operator () (size_type i) const {
  1129. return data_ (ia_ (i));
  1130. }
  1131. BOOST_UBLAS_INLINE
  1132. reference operator () (size_type i) {
  1133. return data_ (ia_ (i));
  1134. }
  1135. BOOST_UBLAS_INLINE
  1136. const_reference operator [] (size_type i) const {
  1137. return (*this) (i);
  1138. }
  1139. BOOST_UBLAS_INLINE
  1140. reference operator [] (size_type i) {
  1141. return (*this) (i);
  1142. }
  1143. #else
  1144. BOOST_UBLAS_INLINE
  1145. reference operator () (size_type i) const {
  1146. return data_ (ia_ (i));
  1147. }
  1148. BOOST_UBLAS_INLINE
  1149. reference operator [] (size_type i) const {
  1150. return (*this) (i);
  1151. }
  1152. #endif
  1153. // ISSUE can this be done in free project function?
  1154. // Although a const function can create a non-const proxy to a non-const object
  1155. // Critical is that vector_type and data_ (vector_closure_type) are const correct
  1156. BOOST_UBLAS_INLINE
  1157. vector_indirect<vector_type, indirect_array_type> project (const range_type &r) const {
  1158. return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (r.preprocess (data_.size ())), 0);
  1159. }
  1160. BOOST_UBLAS_INLINE
  1161. vector_indirect<vector_type, indirect_array_type> project (const slice_type &s) const {
  1162. return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (s.preprocess (data_.size ())), 0);
  1163. }
  1164. BOOST_UBLAS_INLINE
  1165. vector_indirect<vector_type, indirect_array_type> project (const indirect_array_type &ia) const {
  1166. return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (ia.preprocess (data_.size ())), 0);
  1167. }
  1168. // Assignment
  1169. BOOST_UBLAS_INLINE
  1170. vector_indirect &operator = (const vector_indirect &vi) {
  1171. // ISSUE need a temporary, proxy can be overlaping alias
  1172. vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vi));
  1173. return *this;
  1174. }
  1175. BOOST_UBLAS_INLINE
  1176. vector_indirect &assign_temporary (vector_indirect &vi) {
  1177. // assign elements, proxied container remains the same
  1178. vector_assign<scalar_assign> (*this, vi);
  1179. return *this;
  1180. }
  1181. template<class AE>
  1182. BOOST_UBLAS_INLINE
  1183. vector_indirect &operator = (const vector_expression<AE> &ae) {
  1184. vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
  1185. return *this;
  1186. }
  1187. template<class AE>
  1188. BOOST_UBLAS_INLINE
  1189. vector_indirect &assign (const vector_expression<AE> &ae) {
  1190. vector_assign<scalar_assign> (*this, ae);
  1191. return *this;
  1192. }
  1193. template<class AE>
  1194. BOOST_UBLAS_INLINE
  1195. vector_indirect &operator += (const vector_expression<AE> &ae) {
  1196. vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
  1197. return *this;
  1198. }
  1199. template<class AE>
  1200. BOOST_UBLAS_INLINE
  1201. vector_indirect &plus_assign (const vector_expression<AE> &ae) {
  1202. vector_assign<scalar_plus_assign> (*this, ae);
  1203. return *this;
  1204. }
  1205. template<class AE>
  1206. BOOST_UBLAS_INLINE
  1207. vector_indirect &operator -= (const vector_expression<AE> &ae) {
  1208. vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
  1209. return *this;
  1210. }
  1211. template<class AE>
  1212. BOOST_UBLAS_INLINE
  1213. vector_indirect &minus_assign (const vector_expression<AE> &ae) {
  1214. vector_assign<scalar_minus_assign> (*this, ae);
  1215. return *this;
  1216. }
  1217. template<class AT>
  1218. BOOST_UBLAS_INLINE
  1219. vector_indirect &operator *= (const AT &at) {
  1220. vector_assign_scalar<scalar_multiplies_assign> (*this, at);
  1221. return *this;
  1222. }
  1223. template<class AT>
  1224. BOOST_UBLAS_INLINE
  1225. vector_indirect &operator /= (const AT &at) {
  1226. vector_assign_scalar<scalar_divides_assign> (*this, at);
  1227. return *this;
  1228. }
  1229. // Closure comparison
  1230. BOOST_UBLAS_INLINE
  1231. bool same_closure (const vector_indirect &/*vr*/) const {
  1232. return true;
  1233. }
  1234. // Comparison
  1235. BOOST_UBLAS_INLINE
  1236. bool operator == (const vector_indirect &vi) const {
  1237. return (*this).data_ == vi.data_ && ia_ == vi.ia_;
  1238. }
  1239. // Swapping
  1240. BOOST_UBLAS_INLINE
  1241. void swap (vector_indirect vi) {
  1242. if (this != &vi) {
  1243. BOOST_UBLAS_CHECK (size () == vi.size (), bad_size ());
  1244. // Sparse ranges may be nonconformant now.
  1245. // std::swap_ranges (begin (), end (), vi.begin ());
  1246. vector_swap<scalar_swap> (*this, vi);
  1247. }
  1248. }
  1249. BOOST_UBLAS_INLINE
  1250. friend void swap (vector_indirect vi1, vector_indirect vi2) {
  1251. vi1.swap (vi2);
  1252. }
  1253. // Iterator types
  1254. private:
  1255. // Use indirect array as an index - FIXME this fails for packed assignment
  1256. typedef typename IA::const_iterator const_subiterator_type;
  1257. typedef typename IA::const_iterator subiterator_type;
  1258. public:
  1259. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1260. typedef indexed_iterator<vector_indirect<vector_type, indirect_array_type>,
  1261. typename vector_type::iterator::iterator_category> iterator;
  1262. typedef indexed_const_iterator<vector_indirect<vector_type, indirect_array_type>,
  1263. typename vector_type::const_iterator::iterator_category> const_iterator;
  1264. #else
  1265. class const_iterator;
  1266. class iterator;
  1267. #endif
  1268. // Element lookup
  1269. BOOST_UBLAS_INLINE
  1270. const_iterator find (size_type i) const {
  1271. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1272. return const_iterator (*this, i);
  1273. #else
  1274. return const_iterator (*this, ia_.begin () + i);
  1275. #endif
  1276. }
  1277. BOOST_UBLAS_INLINE
  1278. iterator find (size_type i) {
  1279. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1280. return iterator (*this, i);
  1281. #else
  1282. return iterator (*this, ia_.begin () + i);
  1283. #endif
  1284. }
  1285. // Iterators simply are indices.
  1286. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1287. class const_iterator:
  1288. public container_const_reference<vector_indirect>,
  1289. public iterator_base_traits<typename V::const_iterator::iterator_category>::template
  1290. iterator_base<const_iterator, value_type>::type {
  1291. public:
  1292. typedef typename V::const_iterator::difference_type difference_type;
  1293. typedef typename V::const_iterator::value_type value_type;
  1294. typedef typename V::const_reference reference; //FIXME due to indexing access
  1295. typedef typename V::const_iterator::pointer pointer;
  1296. // Construction and destruction
  1297. BOOST_UBLAS_INLINE
  1298. const_iterator ():
  1299. container_const_reference<self_type> (), it_ () {}
  1300. BOOST_UBLAS_INLINE
  1301. const_iterator (const self_type &vi, const const_subiterator_type &it):
  1302. container_const_reference<self_type> (vi), it_ (it) {}
  1303. BOOST_UBLAS_INLINE
  1304. const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
  1305. container_const_reference<self_type> (it ()), it_ (it.it_) {}
  1306. // Arithmetic
  1307. BOOST_UBLAS_INLINE
  1308. const_iterator &operator ++ () {
  1309. ++ it_;
  1310. return *this;
  1311. }
  1312. BOOST_UBLAS_INLINE
  1313. const_iterator &operator -- () {
  1314. -- it_;
  1315. return *this;
  1316. }
  1317. BOOST_UBLAS_INLINE
  1318. const_iterator &operator += (difference_type n) {
  1319. it_ += n;
  1320. return *this;
  1321. }
  1322. BOOST_UBLAS_INLINE
  1323. const_iterator &operator -= (difference_type n) {
  1324. it_ -= n;
  1325. return *this;
  1326. }
  1327. BOOST_UBLAS_INLINE
  1328. difference_type operator - (const const_iterator &it) const {
  1329. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  1330. return it_ - it.it_;
  1331. }
  1332. // Dereference
  1333. BOOST_UBLAS_INLINE
  1334. const_reference operator * () const {
  1335. // FIXME replace find with at_element
  1336. BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
  1337. return (*this) ().data_ (*it_);
  1338. }
  1339. BOOST_UBLAS_INLINE
  1340. const_reference operator [] (difference_type n) const {
  1341. return *(*this + n);
  1342. }
  1343. // Index
  1344. BOOST_UBLAS_INLINE
  1345. size_type index () const {
  1346. return it_.index ();
  1347. }
  1348. // Assignment
  1349. BOOST_UBLAS_INLINE
  1350. const_iterator &operator = (const const_iterator &it) {
  1351. container_const_reference<self_type>::assign (&it ());
  1352. it_ = it.it_;
  1353. return *this;
  1354. }
  1355. // Comparison
  1356. BOOST_UBLAS_INLINE
  1357. bool operator == (const const_iterator &it) const {
  1358. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  1359. return it_ == it.it_;
  1360. }
  1361. BOOST_UBLAS_INLINE
  1362. bool operator < (const const_iterator &it) const {
  1363. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  1364. return it_ < it.it_;
  1365. }
  1366. private:
  1367. const_subiterator_type it_;
  1368. };
  1369. #endif
  1370. BOOST_UBLAS_INLINE
  1371. const_iterator begin () const {
  1372. return find (0);
  1373. }
  1374. BOOST_UBLAS_INLINE
  1375. const_iterator cbegin () const {
  1376. return begin ();
  1377. }
  1378. BOOST_UBLAS_INLINE
  1379. const_iterator end () const {
  1380. return find (size ());
  1381. }
  1382. BOOST_UBLAS_INLINE
  1383. const_iterator cend () const {
  1384. return end ();
  1385. }
  1386. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1387. class iterator:
  1388. public container_reference<vector_indirect>,
  1389. public iterator_base_traits<typename V::iterator::iterator_category>::template
  1390. iterator_base<iterator, value_type>::type {
  1391. public:
  1392. typedef typename V::iterator::difference_type difference_type;
  1393. typedef typename V::iterator::value_type value_type;
  1394. typedef typename V::reference reference; //FIXME due to indexing access
  1395. typedef typename V::iterator::pointer pointer;
  1396. // Construction and destruction
  1397. BOOST_UBLAS_INLINE
  1398. iterator ():
  1399. container_reference<self_type> (), it_ () {}
  1400. BOOST_UBLAS_INLINE
  1401. iterator (self_type &vi, const subiterator_type &it):
  1402. container_reference<self_type> (vi), it_ (it) {}
  1403. // Arithmetic
  1404. BOOST_UBLAS_INLINE
  1405. iterator &operator ++ () {
  1406. ++ it_;
  1407. return *this;
  1408. }
  1409. BOOST_UBLAS_INLINE
  1410. iterator &operator -- () {
  1411. -- it_;
  1412. return *this;
  1413. }
  1414. BOOST_UBLAS_INLINE
  1415. iterator &operator += (difference_type n) {
  1416. it_ += n;
  1417. return *this;
  1418. }
  1419. BOOST_UBLAS_INLINE
  1420. iterator &operator -= (difference_type n) {
  1421. it_ -= n;
  1422. return *this;
  1423. }
  1424. BOOST_UBLAS_INLINE
  1425. difference_type operator - (const iterator &it) const {
  1426. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  1427. return it_ - it.it_;
  1428. }
  1429. // Dereference
  1430. BOOST_UBLAS_INLINE
  1431. reference operator * () const {
  1432. // FIXME replace find with at_element
  1433. BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
  1434. return (*this) ().data_ (*it_);
  1435. }
  1436. BOOST_UBLAS_INLINE
  1437. reference operator [] (difference_type n) const {
  1438. return *(*this + n);
  1439. }
  1440. // Index
  1441. BOOST_UBLAS_INLINE
  1442. size_type index () const {
  1443. return it_.index ();
  1444. }
  1445. // Assignment
  1446. BOOST_UBLAS_INLINE
  1447. iterator &operator = (const iterator &it) {
  1448. container_reference<self_type>::assign (&it ());
  1449. it_ = it.it_;
  1450. return *this;
  1451. }
  1452. // Comparison
  1453. BOOST_UBLAS_INLINE
  1454. bool operator == (const iterator &it) const {
  1455. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  1456. return it_ == it.it_;
  1457. }
  1458. BOOST_UBLAS_INLINE
  1459. bool operator < (const iterator &it) const {
  1460. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  1461. return it_ < it.it_;
  1462. }
  1463. private:
  1464. subiterator_type it_;
  1465. friend class const_iterator;
  1466. };
  1467. #endif
  1468. BOOST_UBLAS_INLINE
  1469. iterator begin () {
  1470. return find (0);
  1471. }
  1472. BOOST_UBLAS_INLINE
  1473. iterator end () {
  1474. return find (size ());
  1475. }
  1476. // Reverse iterator
  1477. typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
  1478. typedef reverse_iterator_base<iterator> reverse_iterator;
  1479. BOOST_UBLAS_INLINE
  1480. const_reverse_iterator rbegin () const {
  1481. return const_reverse_iterator (end ());
  1482. }
  1483. BOOST_UBLAS_INLINE
  1484. const_reverse_iterator crbegin () const {
  1485. return rbegin ();
  1486. }
  1487. BOOST_UBLAS_INLINE
  1488. const_reverse_iterator rend () const {
  1489. return const_reverse_iterator (begin ());
  1490. }
  1491. BOOST_UBLAS_INLINE
  1492. const_reverse_iterator crend () const {
  1493. return rend ();
  1494. }
  1495. BOOST_UBLAS_INLINE
  1496. reverse_iterator rbegin () {
  1497. return reverse_iterator (end ());
  1498. }
  1499. BOOST_UBLAS_INLINE
  1500. reverse_iterator rend () {
  1501. return reverse_iterator (begin ());
  1502. }
  1503. private:
  1504. vector_closure_type data_;
  1505. indirect_array_type ia_;
  1506. };
  1507. // Projections
  1508. template<class V, class A>
  1509. BOOST_UBLAS_INLINE
  1510. vector_indirect<V, indirect_array<A> > project (V &data, const indirect_array<A> &ia) {
  1511. return vector_indirect<V, indirect_array<A> > (data, ia);
  1512. }
  1513. template<class V, class A>
  1514. BOOST_UBLAS_INLINE
  1515. const vector_indirect<const V, indirect_array<A> > project (const V &data, const indirect_array<A> &ia) {
  1516. // ISSUE was: return vector_indirect<V, indirect_array<A> > (const_cast<V &> (data), ia)
  1517. return vector_indirect<const V, indirect_array<A> > (data, ia);
  1518. }
  1519. template<class V, class IA>
  1520. BOOST_UBLAS_INLINE
  1521. vector_indirect<V, IA> project (vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::range_type &r) {
  1522. return data.project (r);
  1523. }
  1524. template<class V, class IA>
  1525. BOOST_UBLAS_INLINE
  1526. const vector_indirect<V, IA> project (const vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::range_type &r) {
  1527. return data.project (r);
  1528. }
  1529. template<class V, class IA>
  1530. BOOST_UBLAS_INLINE
  1531. vector_indirect<V, IA> project (vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::slice_type &s) {
  1532. return data.project (s);
  1533. }
  1534. template<class V, class IA>
  1535. BOOST_UBLAS_INLINE
  1536. const vector_indirect<V, IA> project (const vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::slice_type &s) {
  1537. return data.project (s);
  1538. }
  1539. template<class V, class A>
  1540. BOOST_UBLAS_INLINE
  1541. vector_indirect<V, indirect_array<A> > project (vector_indirect<V, indirect_array<A> > &data, const indirect_array<A> &ia) {
  1542. return data.project (ia);
  1543. }
  1544. template<class V, class A>
  1545. BOOST_UBLAS_INLINE
  1546. const vector_indirect<V, indirect_array<A> > project (const vector_indirect<V, indirect_array<A> > &data, const indirect_array<A> &ia) {
  1547. return data.project (ia);
  1548. }
  1549. // Specialization of temporary_traits
  1550. template <class V>
  1551. struct vector_temporary_traits< vector_indirect<V> >
  1552. : vector_temporary_traits< V > {} ;
  1553. template <class V>
  1554. struct vector_temporary_traits< const vector_indirect<V> >
  1555. : vector_temporary_traits< V > {} ;
  1556. }}}
  1557. #endif