vector_expression.hpp 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671
  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_EXPRESSION_
  13. #define _BOOST_UBLAS_VECTOR_EXPRESSION_
  14. #include <boost/numeric/ublas/expression_types.hpp>
  15. // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
  16. // Iterators based on ideas of Jeremy Siek
  17. //
  18. // Classes that model the Vector Expression concept
  19. namespace boost { namespace numeric { namespace ublas {
  20. template<class E>
  21. class vector_reference:
  22. public vector_expression<vector_reference<E> > {
  23. typedef vector_reference<E> self_type;
  24. public:
  25. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  26. using vector_expression<vector_reference<E> >::operator ();
  27. #endif
  28. typedef typename E::size_type size_type;
  29. typedef typename E::difference_type difference_type;
  30. typedef typename E::value_type value_type;
  31. typedef typename E::const_reference const_reference;
  32. typedef typename boost::mpl::if_<boost::is_const<E>,
  33. typename E::const_reference,
  34. typename E::reference>::type reference;
  35. typedef E referred_type;
  36. typedef const self_type const_closure_type;
  37. typedef self_type closure_type;
  38. typedef typename E::storage_category storage_category;
  39. // Construction and destruction
  40. BOOST_UBLAS_INLINE
  41. explicit vector_reference (referred_type &e):
  42. e_ (e) {}
  43. // Accessors
  44. BOOST_UBLAS_INLINE
  45. size_type size () const {
  46. return expression ().size ();
  47. }
  48. public:
  49. // Expression accessors - const correct
  50. BOOST_UBLAS_INLINE
  51. const referred_type &expression () const {
  52. return e_;
  53. }
  54. BOOST_UBLAS_INLINE
  55. referred_type &expression () {
  56. return e_;
  57. }
  58. public:
  59. // Element access
  60. #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
  61. BOOST_UBLAS_INLINE
  62. const_reference operator () (size_type i) const {
  63. return expression () (i);
  64. }
  65. BOOST_UBLAS_INLINE
  66. reference operator () (size_type i) {
  67. return expression () (i);
  68. }
  69. BOOST_UBLAS_INLINE
  70. const_reference operator [] (size_type i) const {
  71. return expression () [i];
  72. }
  73. BOOST_UBLAS_INLINE
  74. reference operator [] (size_type i) {
  75. return expression () [i];
  76. }
  77. #else
  78. BOOST_UBLAS_INLINE
  79. reference operator () (size_type i) const {
  80. return expression () (i);
  81. }
  82. BOOST_UBLAS_INLINE
  83. reference operator [] (size_type i) const {
  84. return expression () [i];
  85. }
  86. #endif
  87. // Assignment
  88. BOOST_UBLAS_INLINE
  89. vector_reference &operator = (const vector_reference &v) {
  90. expression ().operator = (v);
  91. return *this;
  92. }
  93. template<class AE>
  94. BOOST_UBLAS_INLINE
  95. vector_reference &operator = (const vector_expression<AE> &ae) {
  96. expression ().operator = (ae);
  97. return *this;
  98. }
  99. template<class AE>
  100. BOOST_UBLAS_INLINE
  101. vector_reference &assign (const vector_expression<AE> &ae) {
  102. expression ().assign (ae);
  103. return *this;
  104. }
  105. template<class AE>
  106. BOOST_UBLAS_INLINE
  107. vector_reference &operator += (const vector_expression<AE> &ae) {
  108. expression ().operator += (ae);
  109. return *this;
  110. }
  111. template<class AE>
  112. BOOST_UBLAS_INLINE
  113. vector_reference &plus_assign (const vector_expression<AE> &ae) {
  114. expression ().plus_assign (ae);
  115. return *this;
  116. }
  117. template<class AE>
  118. BOOST_UBLAS_INLINE
  119. vector_reference &operator -= (const vector_expression<AE> &ae) {
  120. expression ().operator -= (ae);
  121. return *this;
  122. }
  123. template<class AE>
  124. BOOST_UBLAS_INLINE
  125. vector_reference &minus_assign (const vector_expression<AE> &ae) {
  126. expression ().minus_assign (ae);
  127. return *this;
  128. }
  129. template<class AT>
  130. BOOST_UBLAS_INLINE
  131. vector_reference &operator *= (const AT &at) {
  132. expression ().operator *= (at);
  133. return *this;
  134. }
  135. template<class AT>
  136. BOOST_UBLAS_INLINE
  137. vector_reference &operator /= (const AT &at) {
  138. expression ().operator /= (at);
  139. return *this;
  140. }
  141. // Swapping
  142. BOOST_UBLAS_INLINE
  143. void swap (vector_reference &v) {
  144. expression ().swap (v.expression ());
  145. }
  146. // Closure comparison
  147. BOOST_UBLAS_INLINE
  148. bool same_closure (const vector_reference &vr) const {
  149. return &(*this).e_ == &vr.e_;
  150. }
  151. // Iterator types
  152. typedef typename E::const_iterator const_iterator;
  153. typedef typename boost::mpl::if_<boost::is_const<E>,
  154. typename E::const_iterator,
  155. typename E::iterator>::type iterator;
  156. // Element lookup
  157. BOOST_UBLAS_INLINE
  158. const_iterator find (size_type i) const {
  159. return expression ().find (i);
  160. }
  161. BOOST_UBLAS_INLINE
  162. iterator find (size_type i) {
  163. return expression ().find (i);
  164. }
  165. // Iterator is the iterator of the referenced expression.
  166. BOOST_UBLAS_INLINE
  167. const_iterator begin () const {
  168. return expression ().begin ();
  169. }
  170. BOOST_UBLAS_INLINE
  171. const_iterator end () const {
  172. return expression ().end ();
  173. }
  174. BOOST_UBLAS_INLINE
  175. iterator begin () {
  176. return expression ().begin ();
  177. }
  178. BOOST_UBLAS_INLINE
  179. iterator end () {
  180. return expression ().end ();
  181. }
  182. // Reverse iterator
  183. typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
  184. typedef reverse_iterator_base<iterator> reverse_iterator;
  185. BOOST_UBLAS_INLINE
  186. const_reverse_iterator rbegin () const {
  187. return const_reverse_iterator (end ());
  188. }
  189. BOOST_UBLAS_INLINE
  190. const_reverse_iterator rend () const {
  191. return const_reverse_iterator (begin ());
  192. }
  193. BOOST_UBLAS_INLINE
  194. reverse_iterator rbegin () {
  195. return reverse_iterator (end ());
  196. }
  197. BOOST_UBLAS_INLINE
  198. reverse_iterator rend () {
  199. return reverse_iterator (begin ());
  200. }
  201. private:
  202. referred_type &e_;
  203. };
  204. template<class E, class F>
  205. class vector_unary:
  206. public vector_expression<vector_unary<E, F> > {
  207. typedef F functor_type;
  208. typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
  209. E,
  210. const E>::type expression_type;
  211. typedef typename boost::mpl::if_<boost::is_const<expression_type>,
  212. typename E::const_closure_type,
  213. typename E::closure_type>::type expression_closure_type;
  214. typedef vector_unary<E, F> self_type;
  215. public:
  216. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  217. using vector_expression<vector_unary<E, F> >::operator ();
  218. #endif
  219. typedef typename E::size_type size_type;
  220. typedef typename E::difference_type difference_type;
  221. typedef typename F::result_type value_type;
  222. typedef value_type const_reference;
  223. typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
  224. typename E::reference,
  225. value_type>::type reference;
  226. typedef const self_type const_closure_type;
  227. typedef self_type closure_type;
  228. typedef unknown_storage_tag storage_category;
  229. // Construction and destruction
  230. BOOST_UBLAS_INLINE
  231. // May be used as mutable expression.
  232. explicit vector_unary (expression_type &e):
  233. e_ (e) {}
  234. // Accessors
  235. BOOST_UBLAS_INLINE
  236. size_type size () const {
  237. return e_.size ();
  238. }
  239. public:
  240. // Expression accessors
  241. BOOST_UBLAS_INLINE
  242. const expression_closure_type &expression () const {
  243. return e_;
  244. }
  245. public:
  246. // Element access
  247. BOOST_UBLAS_INLINE
  248. const_reference operator () (size_type i) const {
  249. return functor_type::apply (e_ (i));
  250. }
  251. BOOST_UBLAS_INLINE
  252. reference operator () (size_type i) {
  253. BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
  254. return e_ (i);
  255. }
  256. BOOST_UBLAS_INLINE
  257. const_reference operator [] (size_type i) const {
  258. return functor_type::apply (e_ [i]);
  259. }
  260. BOOST_UBLAS_INLINE
  261. reference operator [] (size_type i) {
  262. BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
  263. return e_ [i];
  264. }
  265. // Closure comparison
  266. BOOST_UBLAS_INLINE
  267. bool same_closure (const vector_unary &vu) const {
  268. return (*this).expression ().same_closure (vu.expression ());
  269. }
  270. // Iterator types
  271. private:
  272. typedef typename E::const_iterator const_subiterator_type;
  273. typedef const value_type *const_pointer;
  274. public:
  275. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  276. typedef indexed_const_iterator<const_closure_type, typename const_subiterator_type::iterator_category> const_iterator;
  277. typedef const_iterator iterator;
  278. #else
  279. class const_iterator;
  280. typedef const_iterator iterator;
  281. #endif
  282. // Element lookup
  283. BOOST_UBLAS_INLINE
  284. const_iterator find (size_type i) const {
  285. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  286. const_subiterator_type it (e_.find (i));
  287. return const_iterator (*this, it.index ());
  288. #else
  289. return const_iterator (*this, e_.find (i));
  290. #endif
  291. }
  292. // Iterator enhances the iterator of the referenced expression
  293. // with the unary functor.
  294. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  295. class const_iterator:
  296. public container_const_reference<vector_unary>,
  297. public iterator_base_traits<typename E::const_iterator::iterator_category>::template
  298. iterator_base<const_iterator, value_type>::type {
  299. public:
  300. typedef typename E::const_iterator::iterator_category iterator_category;
  301. typedef typename vector_unary::difference_type difference_type;
  302. typedef typename vector_unary::value_type value_type;
  303. typedef typename vector_unary::const_reference reference;
  304. typedef typename vector_unary::const_pointer pointer;
  305. // Construction and destruction
  306. BOOST_UBLAS_INLINE
  307. const_iterator ():
  308. container_const_reference<self_type> (), it_ () {}
  309. BOOST_UBLAS_INLINE
  310. const_iterator (const self_type &vu, const const_subiterator_type &it):
  311. container_const_reference<self_type> (vu), it_ (it) {}
  312. // Arithmetic
  313. BOOST_UBLAS_INLINE
  314. const_iterator &operator ++ () {
  315. ++ it_;
  316. return *this;
  317. }
  318. BOOST_UBLAS_INLINE
  319. const_iterator &operator -- () {
  320. -- it_;
  321. return *this;
  322. }
  323. BOOST_UBLAS_INLINE
  324. const_iterator &operator += (difference_type n) {
  325. it_ += n;
  326. return *this;
  327. }
  328. BOOST_UBLAS_INLINE
  329. const_iterator &operator -= (difference_type n) {
  330. it_ -= n;
  331. return *this;
  332. }
  333. BOOST_UBLAS_INLINE
  334. difference_type operator - (const const_iterator &it) const {
  335. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  336. return it_ - it.it_;
  337. }
  338. // Dereference
  339. BOOST_UBLAS_INLINE
  340. const_reference operator * () const {
  341. return functor_type::apply (*it_);
  342. }
  343. BOOST_UBLAS_INLINE
  344. const_reference operator [] (difference_type n) const {
  345. return *(*this + n);
  346. }
  347. // Index
  348. BOOST_UBLAS_INLINE
  349. size_type index () const {
  350. return it_.index ();
  351. }
  352. // Assignment
  353. BOOST_UBLAS_INLINE
  354. const_iterator &operator = (const const_iterator &it) {
  355. container_const_reference<self_type>::assign (&it ());
  356. it_ = it.it_;
  357. return *this;
  358. }
  359. // Comparison
  360. BOOST_UBLAS_INLINE
  361. bool operator == (const const_iterator &it) const {
  362. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  363. return it_ == it.it_;
  364. }
  365. BOOST_UBLAS_INLINE
  366. bool operator < (const const_iterator &it) const {
  367. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  368. return it_ < it.it_;
  369. }
  370. private:
  371. const_subiterator_type it_;
  372. };
  373. #endif
  374. BOOST_UBLAS_INLINE
  375. const_iterator begin () const {
  376. return find (0);
  377. }
  378. BOOST_UBLAS_INLINE
  379. const_iterator end () const {
  380. return find (size ());
  381. }
  382. // Reverse iterator
  383. typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
  384. BOOST_UBLAS_INLINE
  385. const_reverse_iterator rbegin () const {
  386. return const_reverse_iterator (end ());
  387. }
  388. BOOST_UBLAS_INLINE
  389. const_reverse_iterator rend () const {
  390. return const_reverse_iterator (begin ());
  391. }
  392. private:
  393. expression_closure_type e_;
  394. };
  395. template<class E, class F>
  396. struct vector_unary_traits {
  397. typedef vector_unary<E, F> expression_type;
  398. //FIXME
  399. // #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
  400. typedef expression_type result_type;
  401. // #else
  402. // typedef typename E::vector_temporary_type result_type;
  403. // #endif
  404. };
  405. // (- v) [i] = - v [i]
  406. template<class E>
  407. BOOST_UBLAS_INLINE
  408. typename vector_unary_traits<E, scalar_negate<typename E::value_type> >::result_type
  409. operator - (const vector_expression<E> &e) {
  410. typedef typename vector_unary_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
  411. return expression_type (e ());
  412. }
  413. // (conj v) [i] = conj (v [i])
  414. template<class E>
  415. BOOST_UBLAS_INLINE
  416. typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::result_type
  417. conj (const vector_expression<E> &e) {
  418. typedef typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
  419. return expression_type (e ());
  420. }
  421. // (real v) [i] = real (v [i])
  422. template<class E>
  423. BOOST_UBLAS_INLINE
  424. typename vector_unary_traits<E, scalar_real<typename E::value_type> >::result_type
  425. real (const vector_expression<E> &e) {
  426. typedef typename vector_unary_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
  427. return expression_type (e ());
  428. }
  429. // (imag v) [i] = imag (v [i])
  430. template<class E>
  431. BOOST_UBLAS_INLINE
  432. typename vector_unary_traits<E, scalar_imag<typename E::value_type> >::result_type
  433. imag (const vector_expression<E> &e) {
  434. typedef typename vector_unary_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
  435. return expression_type (e ());
  436. }
  437. // (trans v) [i] = v [i]
  438. template<class E>
  439. BOOST_UBLAS_INLINE
  440. typename vector_unary_traits<const E, scalar_identity<typename E::value_type> >::result_type
  441. trans (const vector_expression<E> &e) {
  442. typedef typename vector_unary_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
  443. return expression_type (e ());
  444. }
  445. template<class E>
  446. BOOST_UBLAS_INLINE
  447. typename vector_unary_traits<E, scalar_identity<typename E::value_type> >::result_type
  448. trans (vector_expression<E> &e) {
  449. typedef typename vector_unary_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
  450. return expression_type (e ());
  451. }
  452. // (herm v) [i] = conj (v [i])
  453. template<class E>
  454. BOOST_UBLAS_INLINE
  455. typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::result_type
  456. herm (const vector_expression<E> &e) {
  457. typedef typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
  458. return expression_type (e ());
  459. }
  460. template<class E1, class E2, class F>
  461. class vector_binary:
  462. public vector_expression<vector_binary<E1, E2, F> > {
  463. typedef E1 expression1_type;
  464. typedef E2 expression2_type;
  465. typedef F functor_type;
  466. typedef typename E1::const_closure_type expression1_closure_type;
  467. typedef typename E2::const_closure_type expression2_closure_type;
  468. typedef vector_binary<E1, E2, F> self_type;
  469. public:
  470. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  471. using vector_expression<vector_binary<E1, E2, F> >::operator ();
  472. #endif
  473. typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
  474. typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
  475. typedef typename F::result_type value_type;
  476. typedef value_type const_reference;
  477. typedef const_reference reference;
  478. typedef const self_type const_closure_type;
  479. typedef const_closure_type closure_type;
  480. typedef unknown_storage_tag storage_category;
  481. // Construction and destruction
  482. BOOST_UBLAS_INLINE
  483. vector_binary (const expression1_type &e1, const expression2_type &e2):
  484. e1_ (e1), e2_ (e2) {}
  485. // Accessors
  486. BOOST_UBLAS_INLINE
  487. size_type size () const {
  488. return BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
  489. }
  490. private:
  491. // Accessors
  492. BOOST_UBLAS_INLINE
  493. const expression1_closure_type &expression1 () const {
  494. return e1_;
  495. }
  496. BOOST_UBLAS_INLINE
  497. const expression2_closure_type &expression2 () const {
  498. return e2_;
  499. }
  500. public:
  501. // Element access
  502. BOOST_UBLAS_INLINE
  503. const_reference operator () (size_type i) const {
  504. return functor_type::apply (e1_ (i), e2_ (i));
  505. }
  506. BOOST_UBLAS_INLINE
  507. const_reference operator [] (size_type i) const {
  508. return functor_type::apply (e1_ [i], e2_ [i]);
  509. }
  510. // Closure comparison
  511. BOOST_UBLAS_INLINE
  512. bool same_closure (const vector_binary &vb) const {
  513. return (*this).expression1 ().same_closure (vb.expression1 ()) &&
  514. (*this).expression2 ().same_closure (vb.expression2 ());
  515. }
  516. // Iterator types
  517. private:
  518. typedef typename E1::const_iterator const_subiterator1_type;
  519. typedef typename E2::const_iterator const_subiterator2_type;
  520. typedef const value_type *const_pointer;
  521. public:
  522. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  523. typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
  524. typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
  525. typedef indexed_const_iterator<const_closure_type, iterator_category> const_iterator;
  526. typedef const_iterator iterator;
  527. #else
  528. class const_iterator;
  529. typedef const_iterator iterator;
  530. #endif
  531. // Element lookup
  532. BOOST_UBLAS_INLINE
  533. const_iterator find (size_type i) const {
  534. const_subiterator1_type it1 (e1_.find (i));
  535. const_subiterator1_type it1_end (e1_.find (size ()));
  536. const_subiterator2_type it2 (e2_.find (i));
  537. const_subiterator2_type it2_end (e2_.find (size ()));
  538. i = (std::min) (it1 != it1_end ? it1.index () : size (),
  539. it2 != it2_end ? it2.index () : size ());
  540. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  541. return const_iterator (*this, i);
  542. #else
  543. return const_iterator (*this, i, it1, it1_end, it2, it2_end);
  544. #endif
  545. }
  546. // Iterator merges the iterators of the referenced expressions and
  547. // enhances them with the binary functor.
  548. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  549. class const_iterator:
  550. public container_const_reference<vector_binary>,
  551. public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
  552. typename E2::const_iterator::iterator_category>::iterator_category>::template
  553. iterator_base<const_iterator, value_type>::type {
  554. public:
  555. typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
  556. typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
  557. typedef typename vector_binary::difference_type difference_type;
  558. typedef typename vector_binary::value_type value_type;
  559. typedef typename vector_binary::const_reference reference;
  560. typedef typename vector_binary::const_pointer pointer;
  561. // Construction and destruction
  562. BOOST_UBLAS_INLINE
  563. const_iterator ():
  564. container_const_reference<self_type> (), i_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
  565. BOOST_UBLAS_INLINE
  566. const_iterator (const self_type &vb, size_type i,
  567. const const_subiterator1_type &it1, const const_subiterator1_type &it1_end,
  568. const const_subiterator2_type &it2, const const_subiterator2_type &it2_end):
  569. container_const_reference<self_type> (vb), i_ (i), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
  570. private:
  571. // Dense specializations
  572. BOOST_UBLAS_INLINE
  573. void increment (dense_random_access_iterator_tag) {
  574. ++ i_; ++ it1_; ++ it2_;
  575. }
  576. BOOST_UBLAS_INLINE
  577. void decrement (dense_random_access_iterator_tag) {
  578. -- i_; -- it1_; -- it2_;
  579. }
  580. BOOST_UBLAS_INLINE
  581. void increment (dense_random_access_iterator_tag, difference_type n) {
  582. i_ += n; it1_ += n; it2_ += n;
  583. }
  584. BOOST_UBLAS_INLINE
  585. void decrement (dense_random_access_iterator_tag, difference_type n) {
  586. i_ -= n; it1_ -= n; it2_ -= n;
  587. }
  588. BOOST_UBLAS_INLINE
  589. value_type dereference (dense_random_access_iterator_tag) const {
  590. return functor_type::apply (*it1_, *it2_);
  591. }
  592. // Packed specializations
  593. BOOST_UBLAS_INLINE
  594. void increment (packed_random_access_iterator_tag) {
  595. if (it1_ != it1_end_)
  596. if (it1_.index () <= i_)
  597. ++ it1_;
  598. if (it2_ != it2_end_)
  599. if (it2_.index () <= i_)
  600. ++ it2_;
  601. ++ i_;
  602. }
  603. BOOST_UBLAS_INLINE
  604. void decrement (packed_random_access_iterator_tag) {
  605. if (it1_ != it1_end_)
  606. if (i_ <= it1_.index ())
  607. -- it1_;
  608. if (it2_ != it2_end_)
  609. if (i_ <= it2_.index ())
  610. -- it2_;
  611. -- i_;
  612. }
  613. BOOST_UBLAS_INLINE
  614. void increment (packed_random_access_iterator_tag, difference_type n) {
  615. while (n > 0) {
  616. increment (packed_random_access_iterator_tag ());
  617. --n;
  618. }
  619. while (n < 0) {
  620. decrement (packed_random_access_iterator_tag ());
  621. ++n;
  622. }
  623. }
  624. BOOST_UBLAS_INLINE
  625. void decrement (packed_random_access_iterator_tag, difference_type n) {
  626. while (n > 0) {
  627. decrement (packed_random_access_iterator_tag ());
  628. --n;
  629. }
  630. while (n < 0) {
  631. increment (packed_random_access_iterator_tag ());
  632. ++n;
  633. }
  634. }
  635. BOOST_UBLAS_INLINE
  636. value_type dereference (packed_random_access_iterator_tag) const {
  637. value_type t1 = value_type/*zero*/();
  638. if (it1_ != it1_end_)
  639. if (it1_.index () == i_)
  640. t1 = *it1_;
  641. value_type t2 = value_type/*zero*/();
  642. if (it2_ != it2_end_)
  643. if (it2_.index () == i_)
  644. t2 = *it2_;
  645. return functor_type::apply (t1, t2);
  646. }
  647. // Sparse specializations
  648. BOOST_UBLAS_INLINE
  649. void increment (sparse_bidirectional_iterator_tag) {
  650. size_type index1 = (*this) ().size ();
  651. if (it1_ != it1_end_) {
  652. if (it1_.index () <= i_)
  653. ++ it1_;
  654. if (it1_ != it1_end_)
  655. index1 = it1_.index ();
  656. }
  657. size_type index2 = (*this) ().size ();
  658. if (it2_ != it2_end_) {
  659. if (it2_.index () <= i_)
  660. ++ it2_;
  661. if (it2_ != it2_end_)
  662. index2 = it2_.index ();
  663. }
  664. i_ = (std::min) (index1, index2);
  665. }
  666. BOOST_UBLAS_INLINE
  667. void decrement (sparse_bidirectional_iterator_tag) {
  668. size_type index1 = (*this) ().size ();
  669. if (it1_ != it1_end_) {
  670. if (i_ <= it1_.index ())
  671. -- it1_;
  672. if (it1_ != it1_end_)
  673. index1 = it1_.index ();
  674. }
  675. size_type index2 = (*this) ().size ();
  676. if (it2_ != it2_end_) {
  677. if (i_ <= it2_.index ())
  678. -- it2_;
  679. if (it2_ != it2_end_)
  680. index2 = it2_.index ();
  681. }
  682. i_ = (std::max) (index1, index2);
  683. }
  684. BOOST_UBLAS_INLINE
  685. void increment (sparse_bidirectional_iterator_tag, difference_type n) {
  686. while (n > 0) {
  687. increment (sparse_bidirectional_iterator_tag ());
  688. --n;
  689. }
  690. while (n < 0) {
  691. decrement (sparse_bidirectional_iterator_tag ());
  692. ++n;
  693. }
  694. }
  695. BOOST_UBLAS_INLINE
  696. void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
  697. while (n > 0) {
  698. decrement (sparse_bidirectional_iterator_tag ());
  699. --n;
  700. }
  701. while (n < 0) {
  702. increment (sparse_bidirectional_iterator_tag ());
  703. ++n;
  704. }
  705. }
  706. BOOST_UBLAS_INLINE
  707. value_type dereference (sparse_bidirectional_iterator_tag) const {
  708. value_type t1 = value_type/*zero*/();
  709. if (it1_ != it1_end_)
  710. if (it1_.index () == i_)
  711. t1 = *it1_;
  712. value_type t2 = value_type/*zero*/();
  713. if (it2_ != it2_end_)
  714. if (it2_.index () == i_)
  715. t2 = *it2_;
  716. return functor_type::apply (t1, t2);
  717. }
  718. public:
  719. // Arithmetic
  720. BOOST_UBLAS_INLINE
  721. const_iterator &operator ++ () {
  722. increment (iterator_category ());
  723. return *this;
  724. }
  725. BOOST_UBLAS_INLINE
  726. const_iterator &operator -- () {
  727. decrement (iterator_category ());
  728. return *this;
  729. }
  730. BOOST_UBLAS_INLINE
  731. const_iterator &operator += (difference_type n) {
  732. increment (iterator_category (), n);
  733. return *this;
  734. }
  735. BOOST_UBLAS_INLINE
  736. const_iterator &operator -= (difference_type n) {
  737. decrement (iterator_category (), n);
  738. return *this;
  739. }
  740. BOOST_UBLAS_INLINE
  741. difference_type operator - (const const_iterator &it) const {
  742. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  743. return index () - it.index ();
  744. }
  745. // Dereference
  746. BOOST_UBLAS_INLINE
  747. const_reference operator * () const {
  748. return dereference (iterator_category ());
  749. }
  750. BOOST_UBLAS_INLINE
  751. const_reference operator [] (difference_type n) const {
  752. return *(*this + n);
  753. }
  754. // Index
  755. BOOST_UBLAS_INLINE
  756. size_type index () const {
  757. return i_;
  758. }
  759. // Assignment
  760. BOOST_UBLAS_INLINE
  761. const_iterator &operator = (const const_iterator &it) {
  762. container_const_reference<self_type>::assign (&it ());
  763. i_ = it.i_;
  764. it1_ = it.it1_;
  765. it1_end_ = it.it1_end_;
  766. it2_ = it.it2_;
  767. it2_end_ = it.it2_end_;
  768. return *this;
  769. }
  770. // Comparison
  771. BOOST_UBLAS_INLINE
  772. bool operator == (const const_iterator &it) const {
  773. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  774. return index () == it.index ();
  775. }
  776. BOOST_UBLAS_INLINE
  777. bool operator < (const const_iterator &it) const {
  778. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  779. return index () < it.index ();
  780. }
  781. private:
  782. size_type i_;
  783. const_subiterator1_type it1_;
  784. const_subiterator1_type it1_end_;
  785. const_subiterator2_type it2_;
  786. const_subiterator2_type it2_end_;
  787. };
  788. #endif
  789. BOOST_UBLAS_INLINE
  790. const_iterator begin () const {
  791. return find (0);
  792. }
  793. BOOST_UBLAS_INLINE
  794. const_iterator end () const {
  795. return find (size ());
  796. }
  797. // Reverse iterator
  798. typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
  799. BOOST_UBLAS_INLINE
  800. const_reverse_iterator rbegin () const {
  801. return const_reverse_iterator (end ());
  802. }
  803. BOOST_UBLAS_INLINE
  804. const_reverse_iterator rend () const {
  805. return const_reverse_iterator (begin ());
  806. }
  807. private:
  808. expression1_closure_type e1_;
  809. expression2_closure_type e2_;
  810. };
  811. template<class E1, class E2, class F>
  812. struct vector_binary_traits {
  813. typedef vector_binary<E1, E2, F> expression_type;
  814. #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
  815. typedef expression_type result_type;
  816. #else
  817. typedef typename E1::vector_temporary_type result_type;
  818. #endif
  819. };
  820. // (v1 + v2) [i] = v1 [i] + v2 [i]
  821. template<class E1, class E2>
  822. BOOST_UBLAS_INLINE
  823. typename vector_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
  824. typename E2::value_type> >::result_type
  825. operator + (const vector_expression<E1> &e1,
  826. const vector_expression<E2> &e2) {
  827. typedef typename vector_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
  828. typename E2::value_type> >::expression_type expression_type;
  829. return expression_type (e1 (), e2 ());
  830. }
  831. // (v1 - v2) [i] = v1 [i] - v2 [i]
  832. template<class E1, class E2>
  833. BOOST_UBLAS_INLINE
  834. typename vector_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
  835. typename E2::value_type> >::result_type
  836. operator - (const vector_expression<E1> &e1,
  837. const vector_expression<E2> &e2) {
  838. typedef typename vector_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
  839. typename E2::value_type> >::expression_type expression_type;
  840. return expression_type (e1 (), e2 ());
  841. }
  842. // (v1 * v2) [i] = v1 [i] * v2 [i]
  843. template<class E1, class E2>
  844. BOOST_UBLAS_INLINE
  845. typename vector_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
  846. typename E2::value_type> >::result_type
  847. element_prod (const vector_expression<E1> &e1,
  848. const vector_expression<E2> &e2) {
  849. typedef typename vector_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
  850. typename E2::value_type> >::expression_type expression_type;
  851. return expression_type (e1 (), e2 ());
  852. }
  853. // (v1 / v2) [i] = v1 [i] / v2 [i]
  854. template<class E1, class E2>
  855. BOOST_UBLAS_INLINE
  856. typename vector_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
  857. typename E2::value_type> >::result_type
  858. element_div (const vector_expression<E1> &e1,
  859. const vector_expression<E2> &e2) {
  860. typedef typename vector_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
  861. typename E2::value_type> >::expression_type expression_type;
  862. return expression_type (e1 (), e2 ());
  863. }
  864. template<class E1, class E2, class F>
  865. class vector_binary_scalar1:
  866. public vector_expression<vector_binary_scalar1<E1, E2, F> > {
  867. typedef F functor_type;
  868. typedef E1 expression1_type;
  869. typedef E2 expression2_type;
  870. public:
  871. typedef const E1& expression1_closure_type;
  872. typedef typename E2::const_closure_type expression2_closure_type;
  873. private:
  874. typedef vector_binary_scalar1<E1, E2, F> self_type;
  875. public:
  876. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  877. using vector_expression<vector_binary_scalar1<E1, E2, F> >::operator ();
  878. #endif
  879. typedef typename E2::size_type size_type;
  880. typedef typename E2::difference_type difference_type;
  881. typedef typename F::result_type value_type;
  882. typedef value_type const_reference;
  883. typedef const_reference reference;
  884. typedef const self_type const_closure_type;
  885. typedef const_closure_type closure_type;
  886. typedef unknown_storage_tag storage_category;
  887. // Construction and destruction
  888. BOOST_UBLAS_INLINE
  889. vector_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
  890. e1_ (e1), e2_ (e2) {}
  891. // Accessors
  892. BOOST_UBLAS_INLINE
  893. size_type size () const {
  894. return e2_.size ();
  895. }
  896. public:
  897. // Element access
  898. BOOST_UBLAS_INLINE
  899. const_reference operator () (size_type i) const {
  900. return functor_type::apply (e1_, e2_ (i));
  901. }
  902. BOOST_UBLAS_INLINE
  903. const_reference operator [] (size_type i) const {
  904. return functor_type::apply (e1_, e2_ [i]);
  905. }
  906. // Closure comparison
  907. BOOST_UBLAS_INLINE
  908. bool same_closure (const vector_binary_scalar1 &vbs1) const {
  909. return &e1_ == &(vbs1.e1_) &&
  910. (*this).e2_.same_closure (vbs1.e2_);
  911. }
  912. // Iterator types
  913. private:
  914. typedef expression1_type const_subiterator1_type;
  915. typedef typename expression2_type::const_iterator const_subiterator2_type;
  916. typedef const value_type *const_pointer;
  917. public:
  918. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  919. typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
  920. typedef const_iterator iterator;
  921. #else
  922. class const_iterator;
  923. typedef const_iterator iterator;
  924. #endif
  925. // Element lookup
  926. BOOST_UBLAS_INLINE
  927. const_iterator find (size_type i) const {
  928. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  929. const_subiterator2_type it (e2_.find (i));
  930. return const_iterator (*this, it.index ());
  931. #else
  932. return const_iterator (*this, const_subiterator1_type (e1_), e2_.find (i));
  933. #endif
  934. }
  935. // Iterator enhances the iterator of the referenced vector expression
  936. // with the binary functor.
  937. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  938. class const_iterator:
  939. public container_const_reference<vector_binary_scalar1>,
  940. public iterator_base_traits<typename E2::const_iterator::iterator_category>::template
  941. iterator_base<const_iterator, value_type>::type {
  942. public:
  943. typedef typename E2::const_iterator::iterator_category iterator_category;
  944. typedef typename vector_binary_scalar1::difference_type difference_type;
  945. typedef typename vector_binary_scalar1::value_type value_type;
  946. typedef typename vector_binary_scalar1::const_reference reference;
  947. typedef typename vector_binary_scalar1::const_pointer pointer;
  948. // Construction and destruction
  949. BOOST_UBLAS_INLINE
  950. const_iterator ():
  951. container_const_reference<self_type> (), it1_ (), it2_ () {}
  952. BOOST_UBLAS_INLINE
  953. const_iterator (const self_type &vbs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
  954. container_const_reference<self_type> (vbs), it1_ (it1), it2_ (it2) {}
  955. // Arithmetic
  956. BOOST_UBLAS_INLINE
  957. const_iterator &operator ++ () {
  958. ++ it2_;
  959. return *this;
  960. }
  961. BOOST_UBLAS_INLINE
  962. const_iterator &operator -- () {
  963. -- it2_;
  964. return *this;
  965. }
  966. BOOST_UBLAS_INLINE
  967. const_iterator &operator += (difference_type n) {
  968. it2_ += n;
  969. return *this;
  970. }
  971. BOOST_UBLAS_INLINE
  972. const_iterator &operator -= (difference_type n) {
  973. it2_ -= n;
  974. return *this;
  975. }
  976. BOOST_UBLAS_INLINE
  977. difference_type operator - (const const_iterator &it) const {
  978. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  979. // FIXME we shouldn't compare floats
  980. // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  981. return it2_ - it.it2_;
  982. }
  983. // Dereference
  984. BOOST_UBLAS_INLINE
  985. const_reference operator * () const {
  986. return functor_type::apply (it1_, *it2_);
  987. }
  988. BOOST_UBLAS_INLINE
  989. const_reference operator [] (difference_type n) const {
  990. return *(*this + n);
  991. }
  992. // Index
  993. BOOST_UBLAS_INLINE
  994. size_type index () const {
  995. return it2_.index ();
  996. }
  997. // Assignment
  998. BOOST_UBLAS_INLINE
  999. const_iterator &operator = (const const_iterator &it) {
  1000. container_const_reference<self_type>::assign (&it ());
  1001. it1_ = it.it1_;
  1002. it2_ = it.it2_;
  1003. return *this;
  1004. }
  1005. // Comparison
  1006. BOOST_UBLAS_INLINE
  1007. bool operator == (const const_iterator &it) const {
  1008. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  1009. // FIXME we shouldn't compare floats
  1010. // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  1011. return it2_ == it.it2_;
  1012. }
  1013. BOOST_UBLAS_INLINE
  1014. bool operator < (const const_iterator &it) const {
  1015. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  1016. // FIXME we shouldn't compare floats
  1017. // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  1018. return it2_ < it.it2_;
  1019. }
  1020. private:
  1021. const_subiterator1_type it1_;
  1022. const_subiterator2_type it2_;
  1023. };
  1024. #endif
  1025. BOOST_UBLAS_INLINE
  1026. const_iterator begin () const {
  1027. return find (0);
  1028. }
  1029. BOOST_UBLAS_INLINE
  1030. const_iterator end () const {
  1031. return find (size ());
  1032. }
  1033. // Reverse iterator
  1034. typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
  1035. BOOST_UBLAS_INLINE
  1036. const_reverse_iterator rbegin () const {
  1037. return const_reverse_iterator (end ());
  1038. }
  1039. BOOST_UBLAS_INLINE
  1040. const_reverse_iterator rend () const {
  1041. return const_reverse_iterator (begin ());
  1042. }
  1043. private:
  1044. expression1_closure_type e1_;
  1045. expression2_closure_type e2_;
  1046. };
  1047. template<class E1, class E2, class F>
  1048. struct vector_binary_scalar1_traits {
  1049. typedef vector_binary_scalar1<E1, E2, F> expression_type; // allow E1 to be builtin type
  1050. #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
  1051. typedef expression_type result_type;
  1052. #else
  1053. typedef typename E2::vector_temporary_type result_type;
  1054. #endif
  1055. };
  1056. // (t * v) [i] = t * v [i]
  1057. template<class T1, class E2>
  1058. BOOST_UBLAS_INLINE
  1059. typename enable_if< is_convertible<T1, typename E2::value_type >,
  1060. typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
  1061. >::type
  1062. operator * (const T1 &e1,
  1063. const vector_expression<E2> &e2) {
  1064. typedef typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
  1065. return expression_type (e1, e2 ());
  1066. }
  1067. template<class E1, class E2, class F>
  1068. class vector_binary_scalar2:
  1069. public vector_expression<vector_binary_scalar2<E1, E2, F> > {
  1070. typedef F functor_type;
  1071. typedef E1 expression1_type;
  1072. typedef E2 expression2_type;
  1073. typedef typename E1::const_closure_type expression1_closure_type;
  1074. typedef const E2& expression2_closure_type;
  1075. typedef vector_binary_scalar2<E1, E2, F> self_type;
  1076. public:
  1077. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  1078. using vector_expression<vector_binary_scalar2<E1, E2, F> >::operator ();
  1079. #endif
  1080. typedef typename E1::size_type size_type;
  1081. typedef typename E1::difference_type difference_type;
  1082. typedef typename F::result_type value_type;
  1083. typedef value_type const_reference;
  1084. typedef const_reference reference;
  1085. typedef const self_type const_closure_type;
  1086. typedef const_closure_type closure_type;
  1087. typedef unknown_storage_tag storage_category;
  1088. // Construction and destruction
  1089. BOOST_UBLAS_INLINE
  1090. vector_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
  1091. e1_ (e1), e2_ (e2) {}
  1092. // Accessors
  1093. BOOST_UBLAS_INLINE
  1094. size_type size () const {
  1095. return e1_.size ();
  1096. }
  1097. public:
  1098. // Element access
  1099. BOOST_UBLAS_INLINE
  1100. const_reference operator () (size_type i) const {
  1101. return functor_type::apply (e1_ (i), e2_);
  1102. }
  1103. BOOST_UBLAS_INLINE
  1104. const_reference operator [] (size_type i) const {
  1105. return functor_type::apply (e1_ [i], e2_);
  1106. }
  1107. // Closure comparison
  1108. BOOST_UBLAS_INLINE
  1109. bool same_closure (const vector_binary_scalar2 &vbs2) const {
  1110. return (*this).e1_.same_closure (vbs2.e1_) &&
  1111. &e2_ == &(vbs2.e2_);
  1112. }
  1113. // Iterator types
  1114. private:
  1115. typedef typename expression1_type::const_iterator const_subiterator1_type;
  1116. typedef expression2_type const_subiterator2_type;
  1117. typedef const value_type *const_pointer;
  1118. public:
  1119. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1120. typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
  1121. typedef const_iterator iterator;
  1122. #else
  1123. class const_iterator;
  1124. typedef const_iterator iterator;
  1125. #endif
  1126. // Element lookup
  1127. BOOST_UBLAS_INLINE
  1128. const_iterator find (size_type i) const {
  1129. #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1130. const_subiterator1_type it (e1_.find (i));
  1131. return const_iterator (*this, it.index ());
  1132. #else
  1133. return const_iterator (*this, e1_.find (i), const_subiterator2_type (e2_));
  1134. #endif
  1135. }
  1136. // Iterator enhances the iterator of the referenced vector expression
  1137. // with the binary functor.
  1138. #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1139. class const_iterator:
  1140. public container_const_reference<vector_binary_scalar2>,
  1141. public iterator_base_traits<typename E1::const_iterator::iterator_category>::template
  1142. iterator_base<const_iterator, value_type>::type {
  1143. public:
  1144. typedef typename E1::const_iterator::iterator_category iterator_category;
  1145. typedef typename vector_binary_scalar2::difference_type difference_type;
  1146. typedef typename vector_binary_scalar2::value_type value_type;
  1147. typedef typename vector_binary_scalar2::const_reference reference;
  1148. typedef typename vector_binary_scalar2::const_pointer pointer;
  1149. // Construction and destruction
  1150. BOOST_UBLAS_INLINE
  1151. const_iterator ():
  1152. container_const_reference<self_type> (), it1_ (), it2_ () {}
  1153. BOOST_UBLAS_INLINE
  1154. const_iterator (const self_type &vbs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
  1155. container_const_reference<self_type> (vbs), it1_ (it1), it2_ (it2) {}
  1156. // Arithmetic
  1157. BOOST_UBLAS_INLINE
  1158. const_iterator &operator ++ () {
  1159. ++ it1_;
  1160. return *this;
  1161. }
  1162. BOOST_UBLAS_INLINE
  1163. const_iterator &operator -- () {
  1164. -- it1_;
  1165. return *this;
  1166. }
  1167. BOOST_UBLAS_INLINE
  1168. const_iterator &operator += (difference_type n) {
  1169. it1_ += n;
  1170. return *this;
  1171. }
  1172. BOOST_UBLAS_INLINE
  1173. const_iterator &operator -= (difference_type n) {
  1174. it1_ -= n;
  1175. return *this;
  1176. }
  1177. BOOST_UBLAS_INLINE
  1178. difference_type operator - (const const_iterator &it) const {
  1179. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  1180. // FIXME we shouldn't compare floats
  1181. // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  1182. return it1_ - it.it1_;
  1183. }
  1184. // Dereference
  1185. BOOST_UBLAS_INLINE
  1186. const_reference operator * () const {
  1187. return functor_type::apply (*it1_, it2_);
  1188. }
  1189. BOOST_UBLAS_INLINE
  1190. const_reference operator [] (difference_type n) const {
  1191. return *(*this + n);
  1192. }
  1193. // Index
  1194. BOOST_UBLAS_INLINE
  1195. size_type index () const {
  1196. return it1_.index ();
  1197. }
  1198. // Assignment
  1199. BOOST_UBLAS_INLINE
  1200. const_iterator &operator = (const const_iterator &it) {
  1201. container_const_reference<self_type>::assign (&it ());
  1202. it1_ = it.it1_;
  1203. it2_ = it.it2_;
  1204. return *this;
  1205. }
  1206. // Comparison
  1207. BOOST_UBLAS_INLINE
  1208. bool operator == (const const_iterator &it) const {
  1209. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  1210. // FIXME we shouldn't compare floats
  1211. // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  1212. return it1_ == it.it1_;
  1213. }
  1214. BOOST_UBLAS_INLINE
  1215. bool operator < (const const_iterator &it) const {
  1216. BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
  1217. // FIXME we shouldn't compare floats
  1218. // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  1219. return it1_ < it.it1_;
  1220. }
  1221. private:
  1222. const_subiterator1_type it1_;
  1223. const_subiterator2_type it2_;
  1224. };
  1225. #endif
  1226. BOOST_UBLAS_INLINE
  1227. const_iterator begin () const {
  1228. return find (0);
  1229. }
  1230. BOOST_UBLAS_INLINE
  1231. const_iterator end () const {
  1232. return find (size ());
  1233. }
  1234. // Reverse iterator
  1235. typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
  1236. BOOST_UBLAS_INLINE
  1237. const_reverse_iterator rbegin () const {
  1238. return const_reverse_iterator (end ());
  1239. }
  1240. BOOST_UBLAS_INLINE
  1241. const_reverse_iterator rend () const {
  1242. return const_reverse_iterator (begin ());
  1243. }
  1244. private:
  1245. expression1_closure_type e1_;
  1246. expression2_closure_type e2_;
  1247. };
  1248. template<class E1, class E2, class F>
  1249. struct vector_binary_scalar2_traits {
  1250. typedef vector_binary_scalar2<E1, E2, F> expression_type; // allow E2 to be builtin type
  1251. #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
  1252. typedef expression_type result_type;
  1253. #else
  1254. typedef typename E1::vector_temporary_type result_type;
  1255. #endif
  1256. };
  1257. // (v * t) [i] = v [i] * t
  1258. template<class E1, class T2>
  1259. BOOST_UBLAS_INLINE
  1260. typename enable_if< is_convertible<T2, typename E1::value_type >,
  1261. typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
  1262. >::type
  1263. operator * (const vector_expression<E1> &e1,
  1264. const T2 &e2) {
  1265. typedef typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
  1266. return expression_type (e1 (), e2);
  1267. }
  1268. // (v / t) [i] = v [i] / t
  1269. template<class E1, class T2>
  1270. BOOST_UBLAS_INLINE
  1271. typename enable_if< is_convertible<T2, typename E1::value_type >,
  1272. typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
  1273. >::type
  1274. operator / (const vector_expression<E1> &e1,
  1275. const T2 &e2) {
  1276. typedef typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
  1277. return expression_type (e1 (), e2);
  1278. }
  1279. template<class E, class F>
  1280. class vector_scalar_unary:
  1281. public scalar_expression<vector_scalar_unary<E, F> > {
  1282. typedef E expression_type;
  1283. typedef F functor_type;
  1284. typedef typename E::const_closure_type expression_closure_type;
  1285. typedef typename E::const_iterator::iterator_category iterator_category;
  1286. typedef vector_scalar_unary<E, F> self_type;
  1287. public:
  1288. typedef typename F::result_type value_type;
  1289. typedef typename E::difference_type difference_type;
  1290. typedef const self_type const_closure_type;
  1291. typedef const_closure_type closure_type;
  1292. typedef unknown_storage_tag storage_category;
  1293. // Construction and destruction
  1294. BOOST_UBLAS_INLINE
  1295. explicit vector_scalar_unary (const expression_type &e):
  1296. e_ (e) {}
  1297. private:
  1298. // Expression accessors
  1299. BOOST_UBLAS_INLINE
  1300. const expression_closure_type &expression () const {
  1301. return e_;
  1302. }
  1303. public:
  1304. BOOST_UBLAS_INLINE
  1305. operator value_type () const {
  1306. return evaluate (iterator_category ());
  1307. }
  1308. private:
  1309. // Dense random access specialization
  1310. BOOST_UBLAS_INLINE
  1311. value_type evaluate (dense_random_access_iterator_tag) const {
  1312. #ifdef BOOST_UBLAS_USE_INDEXING
  1313. return functor_type::apply (e_);
  1314. #elif BOOST_UBLAS_USE_ITERATING
  1315. difference_type size = e_.size ();
  1316. return functor_type::apply (size, e_.begin ());
  1317. #else
  1318. difference_type size = e_.size ();
  1319. if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
  1320. return functor_type::apply (size, e_.begin ());
  1321. else
  1322. return functor_type::apply (e_);
  1323. #endif
  1324. }
  1325. // Packed bidirectional specialization
  1326. BOOST_UBLAS_INLINE
  1327. value_type evaluate (packed_random_access_iterator_tag) const {
  1328. return functor_type::apply (e_.begin (), e_.end ());
  1329. }
  1330. // Sparse bidirectional specialization
  1331. BOOST_UBLAS_INLINE
  1332. value_type evaluate (sparse_bidirectional_iterator_tag) const {
  1333. return functor_type::apply (e_.begin (), e_.end ());
  1334. }
  1335. private:
  1336. expression_closure_type e_;
  1337. };
  1338. template<class E, class F>
  1339. struct vector_scalar_unary_traits {
  1340. typedef vector_scalar_unary<E, F> expression_type;
  1341. #if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET)
  1342. // FIXME don't define USE_SCALAR_ET other then for testing
  1343. // They do not work for complex types
  1344. typedef expression_type result_type;
  1345. #else
  1346. typedef typename F::result_type result_type;
  1347. #endif
  1348. };
  1349. // sum v = sum (v [i])
  1350. template<class E>
  1351. BOOST_UBLAS_INLINE
  1352. typename vector_scalar_unary_traits<E, vector_sum<E> >::result_type
  1353. sum (const vector_expression<E> &e) {
  1354. typedef typename vector_scalar_unary_traits<E, vector_sum<E> >::expression_type expression_type;
  1355. return expression_type (e ());
  1356. }
  1357. // real: norm_1 v = sum (abs (v [i]))
  1358. // complex: norm_1 v = sum (abs (real (v [i])) + abs (imag (v [i])))
  1359. template<class E>
  1360. BOOST_UBLAS_INLINE
  1361. typename vector_scalar_unary_traits<E, vector_norm_1<E> >::result_type
  1362. norm_1 (const vector_expression<E> &e) {
  1363. typedef typename vector_scalar_unary_traits<E, vector_norm_1<E> >::expression_type expression_type;
  1364. return expression_type (e ());
  1365. }
  1366. // real: norm_2 v = sqrt (sum (v [i] * v [i]))
  1367. // complex: norm_2 v = sqrt (sum (v [i] * conj (v [i])))
  1368. template<class E>
  1369. BOOST_UBLAS_INLINE
  1370. typename vector_scalar_unary_traits<E, vector_norm_2<E> >::result_type
  1371. norm_2 (const vector_expression<E> &e) {
  1372. typedef typename vector_scalar_unary_traits<E, vector_norm_2<E> >::expression_type expression_type;
  1373. return expression_type (e ());
  1374. }
  1375. // real: norm_inf v = maximum (abs (v [i]))
  1376. // complex: norm_inf v = maximum (maximum (abs (real (v [i])), abs (imag (v [i]))))
  1377. template<class E>
  1378. BOOST_UBLAS_INLINE
  1379. typename vector_scalar_unary_traits<E, vector_norm_inf<E> >::result_type
  1380. norm_inf (const vector_expression<E> &e) {
  1381. typedef typename vector_scalar_unary_traits<E, vector_norm_inf<E> >::expression_type expression_type;
  1382. return expression_type (e ());
  1383. }
  1384. // real: index_norm_inf v = minimum (i: abs (v [i]) == maximum (abs (v [i])))
  1385. template<class E>
  1386. BOOST_UBLAS_INLINE
  1387. typename vector_scalar_unary_traits<E, vector_index_norm_inf<E> >::result_type
  1388. index_norm_inf (const vector_expression<E> &e) {
  1389. typedef typename vector_scalar_unary_traits<E, vector_index_norm_inf<E> >::expression_type expression_type;
  1390. return expression_type (e ());
  1391. }
  1392. template<class E1, class E2, class F>
  1393. class vector_scalar_binary:
  1394. public scalar_expression<vector_scalar_binary<E1, E2, F> > {
  1395. typedef E1 expression1_type;
  1396. typedef E2 expression2_type;
  1397. typedef F functor_type;
  1398. typedef typename E1::const_closure_type expression1_closure_type;
  1399. typedef typename E2::const_closure_type expression2_closure_type;
  1400. typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
  1401. typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
  1402. typedef vector_scalar_binary<E1, E2, F> self_type;
  1403. public:
  1404. static const unsigned complexity = 1;
  1405. typedef typename F::result_type value_type;
  1406. typedef typename E1::difference_type difference_type;
  1407. typedef const self_type const_closure_type;
  1408. typedef const_closure_type closure_type;
  1409. typedef unknown_storage_tag storage_category;
  1410. // Construction and destruction
  1411. BOOST_UBLAS_INLINE
  1412. vector_scalar_binary (const expression1_type &e1, const expression2_type &e2):
  1413. e1_ (e1), e2_ (e2) {}
  1414. private:
  1415. // Accessors
  1416. BOOST_UBLAS_INLINE
  1417. const expression1_closure_type &expression1 () const {
  1418. return e1_;
  1419. }
  1420. BOOST_UBLAS_INLINE
  1421. const expression2_closure_type &expression2 () const {
  1422. return e2_;
  1423. }
  1424. public:
  1425. BOOST_UBLAS_INLINE
  1426. operator value_type () const {
  1427. return evaluate (iterator_category ());
  1428. }
  1429. private:
  1430. // Dense random access specialization
  1431. BOOST_UBLAS_INLINE
  1432. value_type evaluate (dense_random_access_iterator_tag) const {
  1433. BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
  1434. #ifdef BOOST_UBLAS_USE_INDEXING
  1435. return functor_type::apply (e1_, e2_);
  1436. #elif BOOST_UBLAS_USE_ITERATING
  1437. difference_type size = BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
  1438. return functor_type::apply (size, e1_.begin (), e2_.begin ());
  1439. #else
  1440. difference_type size = BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
  1441. if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
  1442. return functor_type::apply (size, e1_.begin (), e2_.begin ());
  1443. else
  1444. return functor_type::apply (e1_, e2_);
  1445. #endif
  1446. }
  1447. // Packed bidirectional specialization
  1448. BOOST_UBLAS_INLINE
  1449. value_type evaluate (packed_random_access_iterator_tag) const {
  1450. BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
  1451. return functor_type::apply (e1_.begin (), e1_.end (), e2_.begin (), e2_.end ());
  1452. }
  1453. // Sparse bidirectional specialization
  1454. BOOST_UBLAS_INLINE
  1455. value_type evaluate (sparse_bidirectional_iterator_tag) const {
  1456. BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
  1457. return functor_type::apply (e1_.begin (), e1_.end (), e2_.begin (), e2_.end (), sparse_bidirectional_iterator_tag ());
  1458. }
  1459. private:
  1460. expression1_closure_type e1_;
  1461. expression2_closure_type e2_;
  1462. };
  1463. template<class E1, class E2, class F>
  1464. struct vector_scalar_binary_traits {
  1465. typedef vector_scalar_binary<E1, E2, F> expression_type;
  1466. #if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET)
  1467. // FIXME don't define USE_SCALAR_ET other then for testing
  1468. // They do not work for complex types
  1469. typedef expression_type result_type;
  1470. #else
  1471. typedef typename F::result_type result_type;
  1472. #endif
  1473. };
  1474. // inner_prod (v1, v2) = sum (v1 [i] * v2 [i])
  1475. template<class E1, class E2>
  1476. BOOST_UBLAS_INLINE
  1477. typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
  1478. typename promote_traits<typename E1::value_type,
  1479. typename E2::value_type>::promote_type> >::result_type
  1480. inner_prod (const vector_expression<E1> &e1,
  1481. const vector_expression<E2> &e2) {
  1482. typedef typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
  1483. typename promote_traits<typename E1::value_type,
  1484. typename E2::value_type>::promote_type> >::expression_type expression_type;
  1485. return expression_type (e1 (), e2 ());
  1486. }
  1487. template<class E1, class E2>
  1488. BOOST_UBLAS_INLINE
  1489. typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
  1490. typename type_traits<typename promote_traits<typename E1::value_type,
  1491. typename E2::value_type>::promote_type>::precision_type> >::result_type
  1492. prec_inner_prod (const vector_expression<E1> &e1,
  1493. const vector_expression<E2> &e2) {
  1494. typedef typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
  1495. typename type_traits<typename promote_traits<typename E1::value_type,
  1496. typename E2::value_type>::promote_type>::precision_type> >::expression_type expression_type;
  1497. return expression_type (e1 (), e2 ());
  1498. }
  1499. }}}
  1500. #endif