storage.hpp 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918
  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_STORAGE_H
  13. #define BOOST_UBLAS_STORAGE_H
  14. #include <algorithm>
  15. #ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR
  16. #include <boost/shared_array.hpp>
  17. #endif
  18. #include <boost/serialization/array.hpp>
  19. #include <boost/serialization/collection_size_type.hpp>
  20. #include <boost/serialization/nvp.hpp>
  21. #include <boost/numeric/ublas/exception.hpp>
  22. #include <boost/numeric/ublas/traits.hpp>
  23. #include <boost/numeric/ublas/detail/iterator.hpp>
  24. namespace boost { namespace numeric { namespace ublas {
  25. // Base class for Storage Arrays - see the Barton Nackman trick
  26. template<class E>
  27. class storage_array:
  28. private nonassignable {
  29. };
  30. // Unbounded array - with allocator
  31. template<class T, class ALLOC>
  32. class unbounded_array:
  33. public storage_array<unbounded_array<T, ALLOC> > {
  34. typedef unbounded_array<T, ALLOC> self_type;
  35. public:
  36. typedef ALLOC allocator_type;
  37. typedef typename ALLOC::size_type size_type;
  38. typedef typename ALLOC::difference_type difference_type;
  39. typedef T value_type;
  40. typedef const T &const_reference;
  41. typedef T &reference;
  42. typedef const T *const_pointer;
  43. typedef T *pointer;
  44. typedef const_pointer const_iterator;
  45. typedef pointer iterator;
  46. // Construction and destruction
  47. explicit BOOST_UBLAS_INLINE
  48. unbounded_array (const ALLOC &a = ALLOC()):
  49. alloc_ (a), size_ (0) {
  50. data_ = 0;
  51. }
  52. explicit BOOST_UBLAS_INLINE
  53. unbounded_array (size_type size, const ALLOC &a = ALLOC()):
  54. alloc_(a), size_ (size) {
  55. if (size_) {
  56. data_ = alloc_.allocate (size_);
  57. if (! detail::has_trivial_constructor<T>::value) {
  58. for (pointer d = data_; d != data_ + size_; ++d)
  59. alloc_.construct(d, value_type());
  60. }
  61. }
  62. else
  63. data_ = 0;
  64. }
  65. // No value initialised, but still be default constructed
  66. BOOST_UBLAS_INLINE
  67. unbounded_array (size_type size, const value_type &init, const ALLOC &a = ALLOC()):
  68. alloc_ (a), size_ (size) {
  69. if (size_) {
  70. data_ = alloc_.allocate (size_);
  71. std::uninitialized_fill (begin(), end(), init);
  72. }
  73. else
  74. data_ = 0;
  75. }
  76. BOOST_UBLAS_INLINE
  77. unbounded_array (const unbounded_array &c):
  78. storage_array<unbounded_array<T, ALLOC> >(),
  79. alloc_ (c.alloc_), size_ (c.size_) {
  80. if (size_) {
  81. data_ = alloc_.allocate (size_);
  82. std::uninitialized_copy (c.begin(), c.end(), begin());
  83. }
  84. else
  85. data_ = 0;
  86. }
  87. BOOST_UBLAS_INLINE
  88. ~unbounded_array () {
  89. if (size_) {
  90. if (! detail::has_trivial_destructor<T>::value) {
  91. // std::_Destroy (begin(), end(), alloc_);
  92. const iterator i_end = end();
  93. for (iterator i = begin (); i != i_end; ++i) {
  94. iterator_destroy (i);
  95. }
  96. }
  97. alloc_.deallocate (data_, size_);
  98. }
  99. }
  100. // Resizing
  101. private:
  102. BOOST_UBLAS_INLINE
  103. void resize_internal (const size_type size, const value_type init, const bool preserve) {
  104. if (size != size_) {
  105. pointer p_data = data_;
  106. if (size) {
  107. data_ = alloc_.allocate (size);
  108. if (preserve) {
  109. pointer si = p_data;
  110. pointer di = data_;
  111. if (size < size_) {
  112. for (; di != data_ + size; ++di) {
  113. alloc_.construct (di, *si);
  114. ++si;
  115. }
  116. }
  117. else {
  118. for (pointer si = p_data; si != p_data + size_; ++si) {
  119. alloc_.construct (di, *si);
  120. ++di;
  121. }
  122. for (; di != data_ + size; ++di) {
  123. alloc_.construct (di, init);
  124. }
  125. }
  126. }
  127. else {
  128. if (! detail::has_trivial_constructor<T>::value) {
  129. for (pointer di = data_; di != data_ + size; ++di)
  130. alloc_.construct (di, value_type());
  131. }
  132. }
  133. }
  134. if (size_) {
  135. if (! detail::has_trivial_destructor<T>::value) {
  136. for (pointer si = p_data; si != p_data + size_; ++si)
  137. alloc_.destroy (si);
  138. }
  139. alloc_.deallocate (p_data, size_);
  140. }
  141. if (!size)
  142. data_ = 0;
  143. size_ = size;
  144. }
  145. }
  146. public:
  147. BOOST_UBLAS_INLINE
  148. void resize (size_type size) {
  149. resize_internal (size, value_type (), false);
  150. }
  151. BOOST_UBLAS_INLINE
  152. void resize (size_type size, value_type init) {
  153. resize_internal (size, init, true);
  154. }
  155. // Random Access Container
  156. BOOST_UBLAS_INLINE
  157. size_type max_size () const {
  158. return ALLOC ().max_size();
  159. }
  160. BOOST_UBLAS_INLINE
  161. bool empty () const {
  162. return size_ == 0;
  163. }
  164. BOOST_UBLAS_INLINE
  165. size_type size () const {
  166. return size_;
  167. }
  168. // Element access
  169. BOOST_UBLAS_INLINE
  170. const_reference operator [] (size_type i) const {
  171. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  172. return data_ [i];
  173. }
  174. BOOST_UBLAS_INLINE
  175. reference operator [] (size_type i) {
  176. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  177. return data_ [i];
  178. }
  179. // Assignment
  180. BOOST_UBLAS_INLINE
  181. unbounded_array &operator = (const unbounded_array &a) {
  182. if (this != &a) {
  183. resize (a.size_);
  184. std::copy (a.data_, a.data_ + a.size_, data_);
  185. }
  186. return *this;
  187. }
  188. BOOST_UBLAS_INLINE
  189. unbounded_array &assign_temporary (unbounded_array &a) {
  190. swap (a);
  191. return *this;
  192. }
  193. // Swapping
  194. BOOST_UBLAS_INLINE
  195. void swap (unbounded_array &a) {
  196. if (this != &a) {
  197. std::swap (size_, a.size_);
  198. std::swap (data_, a.data_);
  199. }
  200. }
  201. BOOST_UBLAS_INLINE
  202. friend void swap (unbounded_array &a1, unbounded_array &a2) {
  203. a1.swap (a2);
  204. }
  205. BOOST_UBLAS_INLINE
  206. const_iterator begin () const {
  207. return data_;
  208. }
  209. BOOST_UBLAS_INLINE
  210. const_iterator end () const {
  211. return data_ + size_;
  212. }
  213. BOOST_UBLAS_INLINE
  214. iterator begin () {
  215. return data_;
  216. }
  217. BOOST_UBLAS_INLINE
  218. iterator end () {
  219. return data_ + size_;
  220. }
  221. // Reverse iterators
  222. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  223. typedef std::reverse_iterator<iterator> reverse_iterator;
  224. BOOST_UBLAS_INLINE
  225. const_reverse_iterator rbegin () const {
  226. return const_reverse_iterator (end ());
  227. }
  228. BOOST_UBLAS_INLINE
  229. const_reverse_iterator rend () const {
  230. return const_reverse_iterator (begin ());
  231. }
  232. BOOST_UBLAS_INLINE
  233. reverse_iterator rbegin () {
  234. return reverse_iterator (end ());
  235. }
  236. BOOST_UBLAS_INLINE
  237. reverse_iterator rend () {
  238. return reverse_iterator (begin ());
  239. }
  240. // Allocator
  241. allocator_type get_allocator () {
  242. return alloc_;
  243. }
  244. private:
  245. friend class boost::serialization::access;
  246. // Serialization
  247. template<class Archive>
  248. void serialize(Archive & ar, const unsigned int version)
  249. {
  250. serialization::collection_size_type s(size_);
  251. ar & serialization::make_nvp("size",s);
  252. if ( Archive::is_loading::value ) {
  253. resize(s);
  254. }
  255. ar & serialization::make_array(data_, s);
  256. }
  257. private:
  258. // Handle explict destroy on a (possibly indexed) iterator
  259. BOOST_UBLAS_INLINE
  260. static void iterator_destroy (iterator &i) {
  261. (&(*i)) -> ~value_type ();
  262. }
  263. ALLOC alloc_;
  264. size_type size_;
  265. pointer data_;
  266. };
  267. // Bounded array - with allocator for size_type and difference_type
  268. template<class T, std::size_t N, class ALLOC>
  269. class bounded_array:
  270. public storage_array<bounded_array<T, N, ALLOC> > {
  271. typedef bounded_array<T, N, ALLOC> self_type;
  272. public:
  273. // No allocator_type as ALLOC is not used for allocation
  274. typedef typename ALLOC::size_type size_type;
  275. typedef typename ALLOC::difference_type difference_type;
  276. typedef T value_type;
  277. typedef const T &const_reference;
  278. typedef T &reference;
  279. typedef const T *const_pointer;
  280. typedef T *pointer;
  281. typedef const_pointer const_iterator;
  282. typedef pointer iterator;
  283. // Construction and destruction
  284. BOOST_UBLAS_INLINE
  285. bounded_array ():
  286. size_ (0) /*, data_ ()*/ { // size 0 - use bounded_vector to default construct with size N
  287. }
  288. explicit BOOST_UBLAS_INLINE
  289. bounded_array (size_type size):
  290. size_ (size) /*, data_ ()*/ {
  291. BOOST_UBLAS_CHECK (size_ <= N, bad_size ());
  292. // data_ (an array) elements are already default constructed
  293. }
  294. BOOST_UBLAS_INLINE
  295. bounded_array (size_type size, const value_type &init):
  296. size_ (size) /*, data_ ()*/ {
  297. BOOST_UBLAS_CHECK (size_ <= N, bad_size ());
  298. // ISSUE elements should be value constructed here, but we must fill instead as already default constructed
  299. std::fill (begin(), end(), init) ;
  300. }
  301. BOOST_UBLAS_INLINE
  302. bounded_array (const bounded_array &c):
  303. size_ (c.size_) {
  304. // ISSUE elements should be copy constructed here, but we must copy instead as already default constructed
  305. std::copy (c.begin(), c.end(), begin());
  306. }
  307. // Resizing
  308. BOOST_UBLAS_INLINE
  309. void resize (size_type size) {
  310. BOOST_UBLAS_CHECK (size <= N, bad_size ());
  311. size_ = size;
  312. }
  313. BOOST_UBLAS_INLINE
  314. void resize (size_type size, value_type init) {
  315. BOOST_UBLAS_CHECK (size <= N, bad_size ());
  316. if (size > size_)
  317. std::fill (data_ + size_, data_ + size, init);
  318. size_ = size;
  319. }
  320. // Random Access Container
  321. BOOST_UBLAS_INLINE
  322. size_type max_size () const {
  323. return ALLOC ().max_size();
  324. }
  325. BOOST_UBLAS_INLINE
  326. bool empty () const {
  327. return size_ == 0;
  328. }
  329. BOOST_UBLAS_INLINE
  330. size_type size () const {
  331. return size_;
  332. }
  333. // Element access
  334. BOOST_UBLAS_INLINE
  335. const_reference operator [] (size_type i) const {
  336. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  337. return data_ [i];
  338. }
  339. BOOST_UBLAS_INLINE
  340. reference operator [] (size_type i) {
  341. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  342. return data_ [i];
  343. }
  344. // Assignment
  345. BOOST_UBLAS_INLINE
  346. bounded_array &operator = (const bounded_array &a) {
  347. if (this != &a) {
  348. resize (a.size_);
  349. std::copy (a.data_, a.data_ + a.size_, data_);
  350. }
  351. return *this;
  352. }
  353. BOOST_UBLAS_INLINE
  354. bounded_array &assign_temporary (bounded_array &a) {
  355. *this = a;
  356. return *this;
  357. }
  358. // Swapping
  359. BOOST_UBLAS_INLINE
  360. void swap (bounded_array &a) {
  361. if (this != &a) {
  362. std::swap (size_, a.size_);
  363. std::swap_ranges (data_, data_ + (std::max) (size_, a.size_), a.data_);
  364. }
  365. }
  366. BOOST_UBLAS_INLINE
  367. friend void swap (bounded_array &a1, bounded_array &a2) {
  368. a1.swap (a2);
  369. }
  370. BOOST_UBLAS_INLINE
  371. const_iterator begin () const {
  372. return data_;
  373. }
  374. BOOST_UBLAS_INLINE
  375. const_iterator end () const {
  376. return data_ + size_;
  377. }
  378. BOOST_UBLAS_INLINE
  379. iterator begin () {
  380. return data_;
  381. }
  382. BOOST_UBLAS_INLINE
  383. iterator end () {
  384. return data_ + size_;
  385. }
  386. // Reverse iterators
  387. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  388. typedef std::reverse_iterator<iterator> reverse_iterator;
  389. BOOST_UBLAS_INLINE
  390. const_reverse_iterator rbegin () const {
  391. return const_reverse_iterator (end ());
  392. }
  393. BOOST_UBLAS_INLINE
  394. const_reverse_iterator rend () const {
  395. return const_reverse_iterator (begin ());
  396. }
  397. BOOST_UBLAS_INLINE
  398. reverse_iterator rbegin () {
  399. return reverse_iterator (end ());
  400. }
  401. BOOST_UBLAS_INLINE
  402. reverse_iterator rend () {
  403. return reverse_iterator (begin ());
  404. }
  405. private:
  406. // Serialization
  407. friend class boost::serialization::access;
  408. template<class Archive>
  409. void serialize(Archive & ar, const unsigned int version)
  410. {
  411. serialization::collection_size_type s(size_);
  412. ar & serialization::make_nvp("size", s);
  413. if ( Archive::is_loading::value ) {
  414. if (s > N) bad_size("too large size in bounded_array::load()\n").raise();
  415. resize(s);
  416. }
  417. ar & serialization::make_array(data_, s);
  418. }
  419. private:
  420. size_type size_;
  421. // MSVC does not like arrays of size 0 in base classes. Hence, this conditionally changes the size to 1
  422. #ifdef _MSC_VER
  423. BOOST_UBLAS_BOUNDED_ARRAY_ALIGN value_type data_ [(N>0)?N:1];
  424. #else
  425. BOOST_UBLAS_BOUNDED_ARRAY_ALIGN value_type data_ [N];
  426. #endif
  427. };
  428. // Array adaptor with normal deep copy semantics of elements
  429. template<class T>
  430. class array_adaptor:
  431. public storage_array<array_adaptor<T> > {
  432. typedef array_adaptor<T> self_type;
  433. public:
  434. typedef std::size_t size_type;
  435. typedef std::ptrdiff_t difference_type;
  436. typedef T value_type;
  437. typedef const T &const_reference;
  438. typedef T &reference;
  439. typedef const T *const_pointer;
  440. typedef T *pointer;
  441. // Construction and destruction
  442. BOOST_UBLAS_INLINE
  443. array_adaptor ():
  444. size_ (0), own_ (true), data_ (new value_type [0]) {
  445. }
  446. explicit BOOST_UBLAS_INLINE
  447. array_adaptor (size_type size):
  448. size_ (size), own_ (true), data_ (new value_type [size]) {
  449. }
  450. BOOST_UBLAS_INLINE
  451. array_adaptor (size_type size, const value_type &init):
  452. size_ (size), own_ (true), data_ (new value_type [size]) {
  453. std::fill (data_, data_ + size_, init);
  454. }
  455. BOOST_UBLAS_INLINE
  456. array_adaptor (size_type size, pointer data):
  457. size_ (size), own_ (false), data_ (data) {}
  458. BOOST_UBLAS_INLINE
  459. array_adaptor (const array_adaptor &a):
  460. storage_array<self_type> (),
  461. size_ (a.size_), own_ (true), data_ (new value_type [a.size_]) {
  462. *this = a;
  463. }
  464. BOOST_UBLAS_INLINE
  465. ~array_adaptor () {
  466. if (own_) {
  467. delete [] data_;
  468. }
  469. }
  470. // Resizing
  471. private:
  472. BOOST_UBLAS_INLINE
  473. void resize_internal (size_type size, value_type init, bool preserve = true) {
  474. if (size != size_) {
  475. pointer data = new value_type [size];
  476. if (preserve) {
  477. std::copy (data_, data_ + (std::min) (size, size_), data);
  478. std::fill (data + (std::min) (size, size_), data + size, init);
  479. }
  480. if (own_)
  481. delete [] data_;
  482. size_ = size;
  483. own_ = true;
  484. data_ = data;
  485. }
  486. }
  487. BOOST_UBLAS_INLINE
  488. void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) {
  489. if (data != data_) {
  490. if (preserve) {
  491. std::copy (data_, data_ + (std::min) (size, size_), data);
  492. std::fill (data + (std::min) (size, size_), data + size, init);
  493. }
  494. if (own_)
  495. delete [] data_;
  496. own_ = false;
  497. data_ = data;
  498. }
  499. else {
  500. std::fill (data + (std::min) (size, size_), data + size, init);
  501. }
  502. size_ = size;
  503. }
  504. public:
  505. BOOST_UBLAS_INLINE
  506. void resize (size_type size) {
  507. resize_internal (size, value_type (), false);
  508. }
  509. BOOST_UBLAS_INLINE
  510. void resize (size_type size, value_type init) {
  511. resize_internal (size, init, true);
  512. }
  513. BOOST_UBLAS_INLINE
  514. void resize (size_type size, pointer data) {
  515. resize_internal (size, data, value_type (), false);
  516. }
  517. BOOST_UBLAS_INLINE
  518. void resize (size_type size, pointer data, value_type init) {
  519. resize_internal (size, data, init, true);
  520. }
  521. BOOST_UBLAS_INLINE
  522. size_type size () const {
  523. return size_;
  524. }
  525. // Element access
  526. BOOST_UBLAS_INLINE
  527. const_reference operator [] (size_type i) const {
  528. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  529. return data_ [i];
  530. }
  531. BOOST_UBLAS_INLINE
  532. reference operator [] (size_type i) {
  533. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  534. return data_ [i];
  535. }
  536. // Assignment
  537. BOOST_UBLAS_INLINE
  538. array_adaptor &operator = (const array_adaptor &a) {
  539. if (this != &a) {
  540. resize (a.size_);
  541. std::copy (a.data_, a.data_ + a.size_, data_);
  542. }
  543. return *this;
  544. }
  545. BOOST_UBLAS_INLINE
  546. array_adaptor &assign_temporary (array_adaptor &a) {
  547. if (own_ && a.own_)
  548. swap (a);
  549. else
  550. *this = a;
  551. return *this;
  552. }
  553. // Swapping
  554. BOOST_UBLAS_INLINE
  555. void swap (array_adaptor &a) {
  556. if (this != &a) {
  557. std::swap (size_, a.size_);
  558. std::swap (own_, a.own_);
  559. std::swap (data_, a.data_);
  560. }
  561. }
  562. BOOST_UBLAS_INLINE
  563. friend void swap (array_adaptor &a1, array_adaptor &a2) {
  564. a1.swap (a2);
  565. }
  566. // Iterators simply are pointers.
  567. typedef const_pointer const_iterator;
  568. BOOST_UBLAS_INLINE
  569. const_iterator begin () const {
  570. return data_;
  571. }
  572. BOOST_UBLAS_INLINE
  573. const_iterator end () const {
  574. return data_ + size_;
  575. }
  576. typedef pointer iterator;
  577. BOOST_UBLAS_INLINE
  578. iterator begin () {
  579. return data_;
  580. }
  581. BOOST_UBLAS_INLINE
  582. iterator end () {
  583. return data_ + size_;
  584. }
  585. // Reverse iterators
  586. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  587. typedef std::reverse_iterator<iterator> reverse_iterator;
  588. BOOST_UBLAS_INLINE
  589. const_reverse_iterator rbegin () const {
  590. return const_reverse_iterator (end ());
  591. }
  592. BOOST_UBLAS_INLINE
  593. const_reverse_iterator rend () const {
  594. return const_reverse_iterator (begin ());
  595. }
  596. BOOST_UBLAS_INLINE
  597. reverse_iterator rbegin () {
  598. return reverse_iterator (end ());
  599. }
  600. BOOST_UBLAS_INLINE
  601. reverse_iterator rend () {
  602. return reverse_iterator (begin ());
  603. }
  604. private:
  605. size_type size_;
  606. bool own_;
  607. pointer data_;
  608. };
  609. #ifdef BOOST_UBLAS_SHALLOW_ARRAY_ADAPTOR
  610. // Array adaptor with shallow (reference) copy semantics of elements.
  611. // shared_array is used to maintain reference counts.
  612. // This class breaks the normal copy semantics for a storage container and is very dangerous!
  613. template<class T>
  614. class shallow_array_adaptor:
  615. public storage_array<shallow_array_adaptor<T> > {
  616. typedef shallow_array_adaptor<T> self_type;
  617. template<class TT>
  618. struct leaker {
  619. typedef void result_type;
  620. typedef TT *argument_type;
  621. BOOST_UBLAS_INLINE
  622. result_type operator () (argument_type x) {}
  623. };
  624. public:
  625. typedef std::size_t size_type;
  626. typedef std::ptrdiff_t difference_type;
  627. typedef T value_type;
  628. typedef const T &const_reference;
  629. typedef T &reference;
  630. typedef const T *const_pointer;
  631. typedef T *pointer;
  632. // Construction and destruction
  633. BOOST_UBLAS_INLINE
  634. shallow_array_adaptor ():
  635. size_ (0), own_ (true), data_ (new value_type [0]) {
  636. }
  637. explicit BOOST_UBLAS_INLINE
  638. shallow_array_adaptor (size_type size):
  639. size_ (size), own_ (true), data_ (new value_type [size]) {
  640. }
  641. BOOST_UBLAS_INLINE
  642. shallow_array_adaptor (size_type size, const value_type &init):
  643. size_ (size), own_ (true), data_ (new value_type [size]) {
  644. std::fill (data_.get (), data_.get () + size_, init);
  645. }
  646. BOOST_UBLAS_INLINE
  647. shallow_array_adaptor (size_type size, pointer data):
  648. size_ (size), own_ (false), data_ (data, leaker<value_type> ()) {}
  649. BOOST_UBLAS_INLINE
  650. shallow_array_adaptor (const shallow_array_adaptor &a):
  651. storage_array<self_type> (),
  652. size_ (a.size_), own_ (a.own_), data_ (a.data_) {}
  653. BOOST_UBLAS_INLINE
  654. ~shallow_array_adaptor () {
  655. }
  656. // Resizing
  657. private:
  658. BOOST_UBLAS_INLINE
  659. void resize_internal (size_type size, value_type init, bool preserve = true) {
  660. if (size != size_) {
  661. shared_array<value_type> data (new value_type [size]);
  662. if (preserve) {
  663. std::copy (data_.get (), data_.get () + (std::min) (size, size_), data.get ());
  664. std::fill (data.get () + (std::min) (size, size_), data.get () + size, init);
  665. }
  666. size_ = size;
  667. data_ = data;
  668. }
  669. }
  670. BOOST_UBLAS_INLINE
  671. void resize_internal (size_type size, pointer data, value_type init, bool preserve = true) {
  672. if (preserve) {
  673. std::copy (data_.get (), data_.get () + (std::min) (size, size_), data);
  674. std::fill (data + (std::min) (size, size_), data + size, init);
  675. }
  676. size_ = size;
  677. data_ = data;
  678. }
  679. public:
  680. BOOST_UBLAS_INLINE
  681. void resize (size_type size) {
  682. resize_internal (size, value_type (), false);
  683. }
  684. BOOST_UBLAS_INLINE
  685. void resize (size_type size, value_type init) {
  686. resize_internal (size, init, true);
  687. }
  688. BOOST_UBLAS_INLINE
  689. void resize (size_type size, pointer data) {
  690. resize_internal (size, data, value_type (), false);
  691. }
  692. BOOST_UBLAS_INLINE
  693. void resize (size_type size, pointer data, value_type init) {
  694. resize_internal (size, data, init, true);
  695. }
  696. BOOST_UBLAS_INLINE
  697. size_type size () const {
  698. return size_;
  699. }
  700. // Element access
  701. BOOST_UBLAS_INLINE
  702. const_reference operator [] (size_type i) const {
  703. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  704. return data_ [i];
  705. }
  706. BOOST_UBLAS_INLINE
  707. reference operator [] (size_type i) {
  708. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  709. return data_ [i];
  710. }
  711. // Assignment
  712. BOOST_UBLAS_INLINE
  713. shallow_array_adaptor &operator = (const shallow_array_adaptor &a) {
  714. if (this != &a) {
  715. resize (a.size_);
  716. std::copy (a.data_.get (), a.data_.get () + a.size_, data_.get ());
  717. }
  718. return *this;
  719. }
  720. BOOST_UBLAS_INLINE
  721. shallow_array_adaptor &assign_temporary (shallow_array_adaptor &a) {
  722. if (own_ && a.own_)
  723. swap (a);
  724. else
  725. *this = a;
  726. return *this;
  727. }
  728. // Swapping
  729. BOOST_UBLAS_INLINE
  730. void swap (shallow_array_adaptor &a) {
  731. if (this != &a) {
  732. std::swap (size_, a.size_);
  733. std::swap (own_, a.own_);
  734. std::swap (data_, a.data_);
  735. }
  736. }
  737. BOOST_UBLAS_INLINE
  738. friend void swap (shallow_array_adaptor &a1, shallow_array_adaptor &a2) {
  739. a1.swap (a2);
  740. }
  741. // Iterators simply are pointers.
  742. typedef const_pointer const_iterator;
  743. BOOST_UBLAS_INLINE
  744. const_iterator begin () const {
  745. return data_.get ();
  746. }
  747. BOOST_UBLAS_INLINE
  748. const_iterator end () const {
  749. return data_.get () + size_;
  750. }
  751. typedef pointer iterator;
  752. BOOST_UBLAS_INLINE
  753. iterator begin () {
  754. return data_.get ();
  755. }
  756. BOOST_UBLAS_INLINE
  757. iterator end () {
  758. return data_.get () + size_;
  759. }
  760. // Reverse iterators
  761. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  762. typedef std::reverse_iterator<iterator> reverse_iterator;
  763. BOOST_UBLAS_INLINE
  764. const_reverse_iterator rbegin () const {
  765. return const_reverse_iterator (end ());
  766. }
  767. BOOST_UBLAS_INLINE
  768. const_reverse_iterator rend () const {
  769. return const_reverse_iterator (begin ());
  770. }
  771. BOOST_UBLAS_INLINE
  772. reverse_iterator rbegin () {
  773. return reverse_iterator (end ());
  774. }
  775. BOOST_UBLAS_INLINE
  776. reverse_iterator rend () {
  777. return reverse_iterator (begin ());
  778. }
  779. private:
  780. size_type size_;
  781. bool own_;
  782. shared_array<value_type> data_;
  783. };
  784. #endif
  785. // Range class
  786. template <class Z, class D>
  787. class basic_range {
  788. typedef basic_range<Z, D> self_type;
  789. public:
  790. typedef Z size_type;
  791. typedef D difference_type;
  792. typedef size_type value_type;
  793. typedef value_type const_reference;
  794. typedef const_reference reference;
  795. typedef const value_type *const_pointer;
  796. typedef value_type *pointer;
  797. // Construction and destruction
  798. BOOST_UBLAS_INLINE
  799. basic_range ():
  800. start_ (0), size_ (0) {}
  801. BOOST_UBLAS_INLINE
  802. basic_range (size_type start, size_type stop):
  803. start_ (start), size_ (stop - start) {
  804. BOOST_UBLAS_CHECK (start_ <= stop, bad_index ());
  805. }
  806. BOOST_UBLAS_INLINE
  807. size_type start () const {
  808. return start_;
  809. }
  810. BOOST_UBLAS_INLINE
  811. size_type size () const {
  812. return size_;
  813. }
  814. // Random Access Container
  815. BOOST_UBLAS_INLINE
  816. size_type max_size () const {
  817. return size_;
  818. }
  819. BOOST_UBLAS_INLINE
  820. bool empty () const {
  821. return size_ == 0;
  822. }
  823. // Element access
  824. BOOST_UBLAS_INLINE
  825. const_reference operator () (size_type i) const {
  826. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  827. return start_ + i;
  828. }
  829. // Composition
  830. BOOST_UBLAS_INLINE
  831. basic_range compose (const basic_range &r) const {
  832. return basic_range (start_ + r.start_, start_ + r.start_ + r.size_);
  833. }
  834. // Comparison
  835. BOOST_UBLAS_INLINE
  836. bool operator == (const basic_range &r) const {
  837. return start_ == r.start_ && size_ == r.size_;
  838. }
  839. BOOST_UBLAS_INLINE
  840. bool operator != (const basic_range &r) const {
  841. return ! (*this == r);
  842. }
  843. // Iterator types
  844. private:
  845. // Use and index
  846. typedef size_type const_subiterator_type;
  847. public:
  848. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  849. typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator;
  850. #else
  851. class const_iterator:
  852. public container_const_reference<basic_range>,
  853. public random_access_iterator_base<std::random_access_iterator_tag,
  854. const_iterator, value_type> {
  855. public:
  856. typedef typename basic_range::value_type value_type;
  857. typedef typename basic_range::difference_type difference_type;
  858. typedef typename basic_range::const_reference reference;
  859. typedef typename basic_range::const_pointer pointer;
  860. // Construction and destruction
  861. BOOST_UBLAS_INLINE
  862. const_iterator ():
  863. container_const_reference<basic_range> (), it_ () {}
  864. BOOST_UBLAS_INLINE
  865. const_iterator (const basic_range &r, const const_subiterator_type &it):
  866. container_const_reference<basic_range> (r), it_ (it) {}
  867. // Arithmetic
  868. BOOST_UBLAS_INLINE
  869. const_iterator &operator ++ () {
  870. ++ it_;
  871. return *this;
  872. }
  873. BOOST_UBLAS_INLINE
  874. const_iterator &operator -- () {
  875. BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
  876. -- it_;
  877. return *this;
  878. }
  879. BOOST_UBLAS_INLINE
  880. const_iterator &operator += (difference_type n) {
  881. BOOST_UBLAS_CHECK (n >= 0 || it_ >= size_type(-n), bad_index ());
  882. it_ += n;
  883. return *this;
  884. }
  885. BOOST_UBLAS_INLINE
  886. const_iterator &operator -= (difference_type n) {
  887. BOOST_UBLAS_CHECK (n <= 0 || it_ >= size_type(n), bad_index ());
  888. it_ -= n;
  889. return *this;
  890. }
  891. BOOST_UBLAS_INLINE
  892. difference_type operator - (const const_iterator &it) const {
  893. return it_ - it.it_;
  894. }
  895. // Dereference
  896. BOOST_UBLAS_INLINE
  897. const_reference operator * () const {
  898. BOOST_UBLAS_CHECK ((*this) ().start () <= it_, bad_index ());
  899. BOOST_UBLAS_CHECK (it_ < (*this) ().start () + (*this) ().size (), bad_index ());
  900. return it_;
  901. }
  902. BOOST_UBLAS_INLINE
  903. const_reference operator [] (difference_type n) const {
  904. return *(*this + n);
  905. }
  906. // Index
  907. BOOST_UBLAS_INLINE
  908. size_type index () const {
  909. BOOST_UBLAS_CHECK ((*this) ().start () <= it_, bad_index ());
  910. BOOST_UBLAS_CHECK (it_ < (*this) ().start () + (*this) ().size (), bad_index ());
  911. return it_ - (*this) ().start ();
  912. }
  913. // Assignment
  914. BOOST_UBLAS_INLINE
  915. const_iterator &operator = (const const_iterator &it) {
  916. // Comeau recommends...
  917. this->assign (&it ());
  918. it_ = it.it_;
  919. return *this;
  920. }
  921. // Comparison
  922. BOOST_UBLAS_INLINE
  923. bool operator == (const const_iterator &it) const {
  924. BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
  925. return it_ == it.it_;
  926. }
  927. BOOST_UBLAS_INLINE
  928. bool operator < (const const_iterator &it) const {
  929. BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
  930. return it_ < it.it_;
  931. }
  932. private:
  933. const_subiterator_type it_;
  934. };
  935. #endif
  936. BOOST_UBLAS_INLINE
  937. const_iterator begin () const {
  938. return const_iterator (*this, start_);
  939. }
  940. BOOST_UBLAS_INLINE
  941. const_iterator end () const {
  942. return const_iterator (*this, start_ + size_);
  943. }
  944. // Reverse iterator
  945. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  946. BOOST_UBLAS_INLINE
  947. const_reverse_iterator rbegin () const {
  948. return const_reverse_iterator (end ());
  949. }
  950. BOOST_UBLAS_INLINE
  951. const_reverse_iterator rend () const {
  952. return const_reverse_iterator (begin ());
  953. }
  954. BOOST_UBLAS_INLINE
  955. basic_range preprocess (size_type size) const {
  956. if (this != &all_)
  957. return *this;
  958. return basic_range (0, size);
  959. }
  960. static
  961. BOOST_UBLAS_INLINE
  962. const basic_range &all () {
  963. return all_;
  964. }
  965. private:
  966. size_type start_;
  967. size_type size_;
  968. static const basic_range all_;
  969. };
  970. template <class Z, class D>
  971. const basic_range<Z,D> basic_range<Z,D>::all_ (0, size_type (-1));
  972. // Slice class
  973. template <class Z, class D>
  974. class basic_slice {
  975. typedef basic_slice<Z, D> self_type;
  976. public:
  977. typedef Z size_type;
  978. typedef D difference_type;
  979. typedef size_type value_type;
  980. typedef value_type const_reference;
  981. typedef const_reference reference;
  982. typedef const value_type *const_pointer;
  983. typedef value_type *pointer;
  984. // Construction and destruction
  985. BOOST_UBLAS_INLINE
  986. basic_slice ():
  987. start_ (0), stride_ (0), size_ (0) {}
  988. BOOST_UBLAS_INLINE
  989. basic_slice (size_type start, difference_type stride, size_type size):
  990. start_ (start), stride_ (stride), size_ (size) {}
  991. BOOST_UBLAS_INLINE
  992. size_type start () const {
  993. return start_;
  994. }
  995. BOOST_UBLAS_INLINE
  996. difference_type stride () const {
  997. return stride_;
  998. }
  999. BOOST_UBLAS_INLINE
  1000. size_type size () const {
  1001. return size_;
  1002. }
  1003. // Random Access Container
  1004. BOOST_UBLAS_INLINE
  1005. size_type max_size () const {
  1006. return size_;
  1007. }
  1008. BOOST_UBLAS_INLINE
  1009. bool empty () const {
  1010. return size_ == 0;
  1011. }
  1012. // Element access
  1013. BOOST_UBLAS_INLINE
  1014. const_reference operator () (size_type i) const {
  1015. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  1016. BOOST_UBLAS_CHECK (stride_ >= 0 || start_ >= i * -stride_, bad_index ());
  1017. return start_ + i * stride_;
  1018. }
  1019. // Composition
  1020. BOOST_UBLAS_INLINE
  1021. basic_slice compose (const basic_range<size_type, difference_type> &r) const {
  1022. BOOST_UBLAS_CHECK (stride_ >=0 || start_ >= -stride_ * r.start(), bad_index ());
  1023. return basic_slice (start_ + stride_ * r.start (), stride_, r.size ());
  1024. }
  1025. BOOST_UBLAS_INLINE
  1026. basic_slice compose (const basic_slice &s) const {
  1027. BOOST_UBLAS_CHECK (stride_ >=0 || start_ >= -stride_ * s.start_, bad_index ());
  1028. return basic_slice (start_ + stride_ * s.start_, stride_ * s.stride_, s.size_);
  1029. }
  1030. // Comparison
  1031. BOOST_UBLAS_INLINE
  1032. bool operator == (const basic_slice &s) const {
  1033. return start_ == s.start_ && stride_ == s.stride_ && size_ == s.size_;
  1034. }
  1035. BOOST_UBLAS_INLINE
  1036. bool operator != (const basic_slice &s) const {
  1037. return ! (*this == s);
  1038. }
  1039. // Iterator types
  1040. private:
  1041. // Use and index
  1042. typedef size_type const_subiterator_type;
  1043. public:
  1044. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1045. typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator;
  1046. #else
  1047. class const_iterator:
  1048. public container_const_reference<basic_slice>,
  1049. public random_access_iterator_base<std::random_access_iterator_tag,
  1050. const_iterator, value_type> {
  1051. public:
  1052. typedef typename basic_slice::value_type value_type;
  1053. typedef typename basic_slice::difference_type difference_type;
  1054. typedef typename basic_slice::const_reference reference;
  1055. typedef typename basic_slice::const_pointer pointer;
  1056. // Construction and destruction
  1057. BOOST_UBLAS_INLINE
  1058. const_iterator ():
  1059. container_const_reference<basic_slice> (), it_ () {}
  1060. BOOST_UBLAS_INLINE
  1061. const_iterator (const basic_slice &s, const const_subiterator_type &it):
  1062. container_const_reference<basic_slice> (s), it_ (it) {}
  1063. // Arithmetic
  1064. BOOST_UBLAS_INLINE
  1065. const_iterator &operator ++ () {
  1066. ++it_;
  1067. return *this;
  1068. }
  1069. BOOST_UBLAS_INLINE
  1070. const_iterator &operator -- () {
  1071. BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
  1072. --it_;
  1073. return *this;
  1074. }
  1075. BOOST_UBLAS_INLINE
  1076. const_iterator &operator += (difference_type n) {
  1077. BOOST_UBLAS_CHECK (n >= 0 || it_ >= size_type(-n), bad_index ());
  1078. it_ += n;
  1079. return *this;
  1080. }
  1081. BOOST_UBLAS_INLINE
  1082. const_iterator &operator -= (difference_type n) {
  1083. BOOST_UBLAS_CHECK (n <= 0 || it_ >= size_type(n), bad_index ());
  1084. it_ -= n;
  1085. return *this;
  1086. }
  1087. BOOST_UBLAS_INLINE
  1088. difference_type operator - (const const_iterator &it) const {
  1089. return it_ - it.it_;
  1090. }
  1091. // Dereference
  1092. BOOST_UBLAS_INLINE
  1093. const_reference operator * () const {
  1094. BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ());
  1095. return (*this) ().start () + it_* (*this) ().stride ();
  1096. }
  1097. BOOST_UBLAS_INLINE
  1098. const_reference operator [] (difference_type n) const {
  1099. return *(*this + n);
  1100. }
  1101. // Index
  1102. BOOST_UBLAS_INLINE
  1103. size_type index () const {
  1104. BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ());
  1105. return it_;
  1106. }
  1107. // Assignment
  1108. BOOST_UBLAS_INLINE
  1109. const_iterator &operator = (const const_iterator &it) {
  1110. // Comeau recommends...
  1111. this->assign (&it ());
  1112. it_ = it.it_;
  1113. return *this;
  1114. }
  1115. // Comparison
  1116. BOOST_UBLAS_INLINE
  1117. bool operator == (const const_iterator &it) const {
  1118. BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
  1119. return it_ == it.it_;
  1120. }
  1121. BOOST_UBLAS_INLINE
  1122. bool operator < (const const_iterator &it) const {
  1123. BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
  1124. return it_ < it.it_;
  1125. }
  1126. private:
  1127. const_subiterator_type it_;
  1128. };
  1129. #endif
  1130. BOOST_UBLAS_INLINE
  1131. const_iterator begin () const {
  1132. return const_iterator (*this, 0);
  1133. }
  1134. BOOST_UBLAS_INLINE
  1135. const_iterator end () const {
  1136. return const_iterator (*this, size_);
  1137. }
  1138. // Reverse iterator
  1139. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  1140. BOOST_UBLAS_INLINE
  1141. const_reverse_iterator rbegin () const {
  1142. return const_reverse_iterator (end ());
  1143. }
  1144. BOOST_UBLAS_INLINE
  1145. const_reverse_iterator rend () const {
  1146. return const_reverse_iterator (begin ());
  1147. }
  1148. BOOST_UBLAS_INLINE
  1149. basic_slice preprocess (size_type size) const {
  1150. if (this != &all_)
  1151. return *this;
  1152. return basic_slice (0, 1, size);
  1153. }
  1154. static
  1155. BOOST_UBLAS_INLINE
  1156. const basic_slice &all () {
  1157. return all_;
  1158. }
  1159. private:
  1160. size_type start_;
  1161. difference_type stride_;
  1162. size_type size_;
  1163. static const basic_slice all_;
  1164. };
  1165. template <class Z, class D>
  1166. const basic_slice<Z,D> basic_slice<Z,D>::all_ (0, 1, size_type (-1));
  1167. // Indirect array class
  1168. template<class A>
  1169. class indirect_array {
  1170. typedef indirect_array<A> self_type;
  1171. public:
  1172. typedef A array_type;
  1173. typedef const A const_array_type;
  1174. typedef typename A::size_type size_type;
  1175. typedef typename A::difference_type difference_type;
  1176. typedef typename A::value_type value_type;
  1177. typedef typename A::const_reference const_reference;
  1178. typedef typename A::reference reference;
  1179. typedef typename A::const_pointer const_pointer;
  1180. typedef typename A::pointer pointer;
  1181. // Construction and destruction
  1182. BOOST_UBLAS_INLINE
  1183. indirect_array ():
  1184. size_ (), data_ () {}
  1185. explicit BOOST_UBLAS_INLINE
  1186. indirect_array (size_type size):
  1187. size_ (size), data_ (size) {}
  1188. BOOST_UBLAS_INLINE
  1189. indirect_array (size_type size, const array_type &data):
  1190. size_ (size), data_ (data) {}
  1191. BOOST_UBLAS_INLINE
  1192. indirect_array (pointer start, pointer stop):
  1193. size_ (stop - start), data_ (stop - start) {
  1194. std::copy (start, stop, data_.begin ());
  1195. }
  1196. BOOST_UBLAS_INLINE
  1197. size_type size () const {
  1198. return size_;
  1199. }
  1200. BOOST_UBLAS_INLINE
  1201. const_array_type data () const {
  1202. return data_;
  1203. }
  1204. BOOST_UBLAS_INLINE
  1205. array_type data () {
  1206. return data_;
  1207. }
  1208. // Random Access Container
  1209. BOOST_UBLAS_INLINE
  1210. size_type max_size () const {
  1211. return size_;
  1212. }
  1213. BOOST_UBLAS_INLINE
  1214. bool empty () const {
  1215. return data_.size () == 0;
  1216. }
  1217. // Element access
  1218. BOOST_UBLAS_INLINE
  1219. const_reference operator () (size_type i) const {
  1220. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  1221. return data_ [i];
  1222. }
  1223. BOOST_UBLAS_INLINE
  1224. reference operator () (size_type i) {
  1225. BOOST_UBLAS_CHECK (i < size_, bad_index ());
  1226. return data_ [i];
  1227. }
  1228. BOOST_UBLAS_INLINE
  1229. const_reference operator [] (size_type i) const {
  1230. return (*this) (i);
  1231. }
  1232. BOOST_UBLAS_INLINE
  1233. reference operator [] (size_type i) {
  1234. return (*this) (i);
  1235. }
  1236. // Composition
  1237. BOOST_UBLAS_INLINE
  1238. indirect_array compose (const basic_range<size_type, difference_type> &r) const {
  1239. BOOST_UBLAS_CHECK (r.start () + r.size () <= size_, bad_size ());
  1240. array_type data (r.size ());
  1241. for (size_type i = 0; i < r.size (); ++ i)
  1242. data [i] = data_ [r.start () + i];
  1243. return indirect_array (r.size (), data);
  1244. }
  1245. BOOST_UBLAS_INLINE
  1246. indirect_array compose (const basic_slice<size_type, difference_type> &s) const {
  1247. BOOST_UBLAS_CHECK (s.start () + s.stride () * (s.size () - (s.size () > 0)) <= size (), bad_size ());
  1248. array_type data (s.size ());
  1249. for (size_type i = 0; i < s.size (); ++ i)
  1250. data [i] = data_ [s.start () + s.stride () * i];
  1251. return indirect_array (s.size (), data);
  1252. }
  1253. BOOST_UBLAS_INLINE
  1254. indirect_array compose (const indirect_array &ia) const {
  1255. array_type data (ia.size_);
  1256. for (size_type i = 0; i < ia.size_; ++ i) {
  1257. BOOST_UBLAS_CHECK (ia.data_ [i] <= size_, bad_size ());
  1258. data [i] = data_ [ia.data_ [i]];
  1259. }
  1260. return indirect_array (ia.size_, data);
  1261. }
  1262. // Comparison
  1263. template<class OA>
  1264. BOOST_UBLAS_INLINE
  1265. bool operator == (const indirect_array<OA> &ia) const {
  1266. if (size_ != ia.size_)
  1267. return false;
  1268. for (size_type i = 0; i < BOOST_UBLAS_SAME (size_, ia.size_); ++ i)
  1269. if (data_ [i] != ia.data_ [i])
  1270. return false;
  1271. return true;
  1272. }
  1273. template<class OA>
  1274. BOOST_UBLAS_INLINE
  1275. bool operator != (const indirect_array<OA> &ia) const {
  1276. return ! (*this == ia);
  1277. }
  1278. // Iterator types
  1279. private:
  1280. // Use a index difference
  1281. typedef difference_type const_subiterator_type;
  1282. public:
  1283. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1284. typedef indexed_const_iterator<indirect_array, std::random_access_iterator_tag> const_iterator;
  1285. #else
  1286. class const_iterator:
  1287. public container_const_reference<indirect_array>,
  1288. public random_access_iterator_base<std::random_access_iterator_tag,
  1289. const_iterator, value_type> {
  1290. public:
  1291. typedef typename indirect_array::value_type value_type;
  1292. typedef typename indirect_array::difference_type difference_type;
  1293. typedef typename indirect_array::const_reference reference;
  1294. typedef typename indirect_array::const_pointer pointer;
  1295. // Construction and destruction
  1296. BOOST_UBLAS_INLINE
  1297. const_iterator ():
  1298. container_const_reference<indirect_array> (), it_ () {}
  1299. BOOST_UBLAS_INLINE
  1300. const_iterator (const indirect_array &ia, const const_subiterator_type &it):
  1301. container_const_reference<indirect_array> (ia), it_ (it) {}
  1302. // Arithmetic
  1303. BOOST_UBLAS_INLINE
  1304. const_iterator &operator ++ () {
  1305. ++ it_;
  1306. return *this;
  1307. }
  1308. BOOST_UBLAS_INLINE
  1309. const_iterator &operator -- () {
  1310. -- it_;
  1311. return *this;
  1312. }
  1313. BOOST_UBLAS_INLINE
  1314. const_iterator &operator += (difference_type n) {
  1315. it_ += n;
  1316. return *this;
  1317. }
  1318. BOOST_UBLAS_INLINE
  1319. const_iterator &operator -= (difference_type n) {
  1320. it_ -= n;
  1321. return *this;
  1322. }
  1323. BOOST_UBLAS_INLINE
  1324. difference_type operator - (const const_iterator &it) const {
  1325. return it_ - it.it_;
  1326. }
  1327. // Dereference
  1328. BOOST_UBLAS_INLINE
  1329. const_reference operator * () const {
  1330. return (*this) () (it_);
  1331. }
  1332. BOOST_UBLAS_INLINE
  1333. const_reference operator [] (difference_type n) const {
  1334. return *(*this + n);
  1335. }
  1336. // Index
  1337. BOOST_UBLAS_INLINE
  1338. size_type index () const {
  1339. return it_;
  1340. }
  1341. // Assignment
  1342. BOOST_UBLAS_INLINE
  1343. const_iterator &operator = (const const_iterator &it) {
  1344. // Comeau recommends...
  1345. this->assign (&it ());
  1346. it_ = it.it_;
  1347. return *this;
  1348. }
  1349. // Comparison
  1350. BOOST_UBLAS_INLINE
  1351. bool operator == (const const_iterator &it) const {
  1352. BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
  1353. return it_ == it.it_;
  1354. }
  1355. BOOST_UBLAS_INLINE
  1356. bool operator < (const const_iterator &it) const {
  1357. BOOST_UBLAS_CHECK ((*this) () == it (), external_logic ());
  1358. return it_ < it.it_;
  1359. }
  1360. private:
  1361. const_subiterator_type it_;
  1362. };
  1363. #endif
  1364. BOOST_UBLAS_INLINE
  1365. const_iterator begin () const {
  1366. return const_iterator (*this, 0);
  1367. }
  1368. BOOST_UBLAS_INLINE
  1369. const_iterator end () const {
  1370. return const_iterator (*this, size_);
  1371. }
  1372. // Reverse iterator
  1373. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  1374. BOOST_UBLAS_INLINE
  1375. const_reverse_iterator rbegin () const {
  1376. return const_reverse_iterator (end ());
  1377. }
  1378. BOOST_UBLAS_INLINE
  1379. const_reverse_iterator rend () const {
  1380. return const_reverse_iterator (begin ());
  1381. }
  1382. BOOST_UBLAS_INLINE
  1383. indirect_array preprocess (size_type size) const {
  1384. if (this != &all_)
  1385. return *this;
  1386. indirect_array ia (size);
  1387. for (size_type i = 0; i < size; ++ i)
  1388. ia (i) = i;
  1389. return ia;
  1390. }
  1391. static
  1392. BOOST_UBLAS_INLINE
  1393. const indirect_array &all () {
  1394. return all_;
  1395. }
  1396. private:
  1397. size_type size_;
  1398. array_type data_;
  1399. static const indirect_array all_;
  1400. };
  1401. template<class A>
  1402. const indirect_array<A> indirect_array<A>::all_;
  1403. // Gunter Winkler contributed the classes index_pair, index_pair_array,
  1404. // index_triple and index_triple_array to enable inplace sort of parallel arrays.
  1405. template <class V>
  1406. class index_pair :
  1407. public container_reference<V> {
  1408. typedef index_pair<V> self_type;
  1409. public:
  1410. typedef typename V::size_type size_type;
  1411. BOOST_UBLAS_INLINE
  1412. index_pair(V& v, size_type i) :
  1413. container_reference<V>(v), i_(i),
  1414. v1_(v.data1_[i]), v2_(v.data2_[i]),
  1415. dirty_(false), is_copy_(false) {}
  1416. BOOST_UBLAS_INLINE
  1417. index_pair(const self_type& rhs) :
  1418. container_reference<V>(rhs()), i_(0),
  1419. v1_(rhs.v1_), v2_(rhs.v2_),
  1420. dirty_(false), is_copy_(true) {}
  1421. BOOST_UBLAS_INLINE
  1422. ~index_pair() {
  1423. if (dirty_ && (!is_copy_) ) {
  1424. (*this)().data1_[i_] = v1_;
  1425. (*this)().data2_[i_] = v2_;
  1426. }
  1427. }
  1428. BOOST_UBLAS_INLINE
  1429. self_type& operator=(const self_type& rhs) {
  1430. v1_ = rhs.v1_;
  1431. v2_ = rhs.v2_;
  1432. dirty_ = true;
  1433. return *this;
  1434. }
  1435. BOOST_UBLAS_INLINE
  1436. void swap(self_type& rhs) {
  1437. self_type tmp(rhs);
  1438. rhs = *this;
  1439. *this = tmp;
  1440. }
  1441. BOOST_UBLAS_INLINE
  1442. friend void swap(self_type& lhs, self_type& rhs) {
  1443. lhs.swap(rhs);
  1444. }
  1445. BOOST_UBLAS_INLINE
  1446. bool equal(const self_type& rhs) const {
  1447. return (v1_ == rhs.v1_);
  1448. }
  1449. BOOST_UBLAS_INLINE
  1450. bool less(const self_type& rhs) const {
  1451. return (v1_ < rhs.v1_);
  1452. }
  1453. BOOST_UBLAS_INLINE
  1454. friend bool operator == (const self_type& lhs, const self_type& rhs) {
  1455. return lhs.equal(rhs);
  1456. }
  1457. BOOST_UBLAS_INLINE
  1458. friend bool operator != (const self_type& lhs, const self_type& rhs) {
  1459. return !lhs.equal(rhs);
  1460. }
  1461. BOOST_UBLAS_INLINE
  1462. friend bool operator < (const self_type& lhs, const self_type& rhs) {
  1463. return lhs.less(rhs);
  1464. }
  1465. BOOST_UBLAS_INLINE
  1466. friend bool operator >= (const self_type& lhs, const self_type& rhs) {
  1467. return !lhs.less(rhs);
  1468. }
  1469. BOOST_UBLAS_INLINE
  1470. friend bool operator > (const self_type& lhs, const self_type& rhs) {
  1471. return rhs.less(lhs);
  1472. }
  1473. BOOST_UBLAS_INLINE
  1474. friend bool operator <= (const self_type& lhs, const self_type& rhs) {
  1475. return !rhs.less(lhs);
  1476. }
  1477. private:
  1478. size_type i_;
  1479. typename V::value1_type v1_;
  1480. typename V::value2_type v2_;
  1481. bool dirty_;
  1482. bool is_copy_;
  1483. };
  1484. template <class V1, class V2>
  1485. class index_pair_array:
  1486. private boost::noncopyable {
  1487. typedef index_pair_array<V1, V2> self_type;
  1488. public:
  1489. typedef typename V1::value_type value1_type;
  1490. typedef typename V2::value_type value2_type;
  1491. typedef typename V1::size_type size_type;
  1492. typedef typename V1::difference_type difference_type;
  1493. typedef index_pair<self_type> value_type;
  1494. // There is nothing that can be referenced directly. Always return a copy of the index_pair
  1495. typedef value_type reference;
  1496. typedef const value_type const_reference;
  1497. BOOST_UBLAS_INLINE
  1498. index_pair_array(size_type size, V1& data1, V2& data2) :
  1499. size_(size),data1_(data1),data2_(data2) {}
  1500. BOOST_UBLAS_INLINE
  1501. size_type size() const {
  1502. return size_;
  1503. }
  1504. BOOST_UBLAS_INLINE
  1505. const_reference operator () (size_type i) const {
  1506. return value_type((*this), i);
  1507. }
  1508. BOOST_UBLAS_INLINE
  1509. reference operator () (size_type i) {
  1510. return value_type((*this), i);
  1511. }
  1512. typedef indexed_iterator<self_type, std::random_access_iterator_tag> iterator;
  1513. typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator;
  1514. BOOST_UBLAS_INLINE
  1515. iterator begin() {
  1516. return iterator( (*this), 0);
  1517. }
  1518. BOOST_UBLAS_INLINE
  1519. iterator end() {
  1520. return iterator( (*this), size());
  1521. }
  1522. BOOST_UBLAS_INLINE
  1523. const_iterator begin() const {
  1524. return const_iterator( (*this), 0);
  1525. }
  1526. BOOST_UBLAS_INLINE
  1527. const_iterator end() const {
  1528. return const_iterator( (*this), size());
  1529. }
  1530. // unnecessary function:
  1531. BOOST_UBLAS_INLINE
  1532. bool equal(size_type i1, size_type i2) const {
  1533. return data1_[i1] == data1_[i2];
  1534. }
  1535. BOOST_UBLAS_INLINE
  1536. bool less(size_type i1, size_type i2) const {
  1537. return data1_[i1] < data1_[i2];
  1538. }
  1539. // gives a large speedup
  1540. BOOST_UBLAS_INLINE
  1541. friend void iter_swap(const iterator& lhs, const iterator& rhs) {
  1542. const size_type i1 = lhs.index();
  1543. const size_type i2 = rhs.index();
  1544. std::swap(lhs().data1_[i1], rhs().data1_[i2]);
  1545. std::swap(lhs().data2_[i1], rhs().data2_[i2]);
  1546. }
  1547. private:
  1548. size_type size_;
  1549. V1& data1_;
  1550. V2& data2_;
  1551. // friend class value_type;
  1552. friend class index_pair<self_type>;
  1553. };
  1554. template <class M>
  1555. class index_triple :
  1556. public container_reference<M> {
  1557. typedef index_triple<M> self_type;
  1558. public:
  1559. typedef typename M::size_type size_type;
  1560. BOOST_UBLAS_INLINE
  1561. index_triple(M& m, size_type i) :
  1562. container_reference<M>(m), i_(i),
  1563. v1_(m.data1_[i]), v2_(m.data2_[i]), v3_(m.data3_[i]),
  1564. dirty_(false), is_copy_(false) {}
  1565. BOOST_UBLAS_INLINE
  1566. index_triple(const self_type& rhs) :
  1567. container_reference<M>(rhs()), i_(0),
  1568. v1_(rhs.v1_), v2_(rhs.v2_), v3_(rhs.v3_),
  1569. dirty_(false), is_copy_(true) {}
  1570. BOOST_UBLAS_INLINE
  1571. ~index_triple() {
  1572. if (dirty_ && (!is_copy_) ) {
  1573. (*this)().data1_[i_] = v1_;
  1574. (*this)().data2_[i_] = v2_;
  1575. (*this)().data3_[i_] = v3_;
  1576. }
  1577. }
  1578. BOOST_UBLAS_INLINE
  1579. self_type& operator=(const self_type& rhs) {
  1580. v1_ = rhs.v1_;
  1581. v2_ = rhs.v2_;
  1582. v3_ = rhs.v3_;
  1583. dirty_ = true;
  1584. return *this;
  1585. }
  1586. BOOST_UBLAS_INLINE
  1587. void swap(self_type& rhs) {
  1588. self_type tmp(rhs);
  1589. rhs = *this;
  1590. *this = tmp;
  1591. }
  1592. BOOST_UBLAS_INLINE
  1593. friend void swap(self_type& lhs, self_type& rhs) {
  1594. lhs.swap(rhs);
  1595. }
  1596. BOOST_UBLAS_INLINE
  1597. bool equal(const self_type& rhs) const {
  1598. return ((v1_ == rhs.v1_) && (v2_ == rhs.v2_));
  1599. }
  1600. BOOST_UBLAS_INLINE
  1601. bool less(const self_type& rhs) const {
  1602. return ((v1_ < rhs.v1_) ||
  1603. (v1_ == rhs.v1_ && v2_ < rhs.v2_));
  1604. }
  1605. BOOST_UBLAS_INLINE
  1606. friend bool operator == (const self_type& lhs, const self_type& rhs) {
  1607. return lhs.equal(rhs);
  1608. }
  1609. BOOST_UBLAS_INLINE
  1610. friend bool operator != (const self_type& lhs, const self_type& rhs) {
  1611. return !lhs.equal(rhs);
  1612. }
  1613. BOOST_UBLAS_INLINE
  1614. friend bool operator < (const self_type& lhs, const self_type& rhs) {
  1615. return lhs.less(rhs);
  1616. }
  1617. BOOST_UBLAS_INLINE
  1618. friend bool operator >= (const self_type& lhs, const self_type& rhs) {
  1619. return !lhs.less(rhs);
  1620. }
  1621. BOOST_UBLAS_INLINE
  1622. friend bool operator > (const self_type& lhs, const self_type& rhs) {
  1623. return rhs.less(lhs);
  1624. }
  1625. BOOST_UBLAS_INLINE
  1626. friend bool operator <= (const self_type& lhs, const self_type& rhs) {
  1627. return !rhs.less(lhs);
  1628. }
  1629. private:
  1630. size_type i_;
  1631. typename M::value1_type v1_;
  1632. typename M::value2_type v2_;
  1633. typename M::value3_type v3_;
  1634. bool dirty_;
  1635. bool is_copy_;
  1636. };
  1637. template <class V1, class V2, class V3>
  1638. class index_triple_array:
  1639. private boost::noncopyable {
  1640. typedef index_triple_array<V1, V2, V3> self_type;
  1641. public:
  1642. typedef typename V1::value_type value1_type;
  1643. typedef typename V2::value_type value2_type;
  1644. typedef typename V3::value_type value3_type;
  1645. typedef typename V1::size_type size_type;
  1646. typedef typename V1::difference_type difference_type;
  1647. typedef index_triple<self_type> value_type;
  1648. // There is nothing that can be referenced directly. Always return a copy of the index_triple
  1649. typedef value_type reference;
  1650. typedef const value_type const_reference;
  1651. BOOST_UBLAS_INLINE
  1652. index_triple_array(size_type size, V1& data1, V2& data2, V3& data3) :
  1653. size_(size),data1_(data1),data2_(data2),data3_(data3) {}
  1654. BOOST_UBLAS_INLINE
  1655. size_type size() const {
  1656. return size_;
  1657. }
  1658. BOOST_UBLAS_INLINE
  1659. const_reference operator () (size_type i) const {
  1660. return value_type((*this), i);
  1661. }
  1662. BOOST_UBLAS_INLINE
  1663. reference operator () (size_type i) {
  1664. return value_type((*this), i);
  1665. }
  1666. typedef indexed_iterator<self_type, std::random_access_iterator_tag> iterator;
  1667. typedef indexed_const_iterator<self_type, std::random_access_iterator_tag> const_iterator;
  1668. BOOST_UBLAS_INLINE
  1669. iterator begin() {
  1670. return iterator( (*this), 0);
  1671. }
  1672. BOOST_UBLAS_INLINE
  1673. iterator end() {
  1674. return iterator( (*this), size());
  1675. }
  1676. BOOST_UBLAS_INLINE
  1677. const_iterator begin() const {
  1678. return const_iterator( (*this), 0);
  1679. }
  1680. BOOST_UBLAS_INLINE
  1681. const_iterator end() const {
  1682. return const_iterator( (*this), size());
  1683. }
  1684. // unnecessary function:
  1685. BOOST_UBLAS_INLINE
  1686. bool equal(size_type i1, size_type i2) const {
  1687. return ((data1_[i1] == data1_[i2]) && (data2_[i1] == data2_[i2]));
  1688. }
  1689. BOOST_UBLAS_INLINE
  1690. bool less(size_type i1, size_type i2) const {
  1691. return ((data1_[i1] < data1_[i2]) ||
  1692. (data1_[i1] == data1_[i2] && data2_[i1] < data2_[i2]));
  1693. }
  1694. // gives a large speedup
  1695. BOOST_UBLAS_INLINE
  1696. friend void iter_swap(const iterator& lhs, const iterator& rhs) {
  1697. const size_type i1 = lhs.index();
  1698. const size_type i2 = rhs.index();
  1699. std::swap(lhs().data1_[i1], rhs().data1_[i2]);
  1700. std::swap(lhs().data2_[i1], rhs().data2_[i2]);
  1701. std::swap(lhs().data3_[i1], rhs().data3_[i2]);
  1702. }
  1703. private:
  1704. size_type size_;
  1705. V1& data1_;
  1706. V2& data2_;
  1707. V3& data3_;
  1708. // friend class value_type;
  1709. friend class index_triple<self_type>;
  1710. };
  1711. }}}
  1712. #endif