expression_types.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. // Copyright (c) 2000-2013
  2. // Joerg Walter, Mathias Koch. David Bellot
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // The authors gratefully acknowledge the support of
  9. // GeNeSys mbH & Co. KG in producing this work.
  10. //
  11. #ifndef _BOOST_UBLAS_EXPRESSION_TYPE_
  12. #define _BOOST_UBLAS_EXPRESSION_TYPE_
  13. #include <boost/numeric/ublas/exception.hpp>
  14. #include <boost/numeric/ublas/traits.hpp>
  15. #include <boost/numeric/ublas/functional.hpp>
  16. // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
  17. // Iterators based on ideas of Jeremy Siek
  18. namespace boost { namespace numeric { namespace ublas {
  19. /** \brief Base class for uBLAS statically derived expressions using the the Barton Nackman trick
  20. *
  21. * This is a NonAssignable class
  22. * Directly implement nonassignable - simplifes debugging call trace!
  23. *
  24. * \tparam E an expression type
  25. */
  26. template<class E>
  27. class ublas_expression {
  28. public:
  29. typedef E expression_type;
  30. /* E can be an incomplete type - to define the following we would need more template arguments
  31. typedef typename E::type_category type_category;
  32. typedef typename E::value_type value_type;
  33. */
  34. protected:
  35. ublas_expression () {}
  36. ~ublas_expression () {}
  37. private:
  38. const ublas_expression& operator= (const ublas_expression &);
  39. };
  40. /** \brief Base class for Scalar Expression models
  41. *
  42. * It does not model the Scalar Expression concept but all derived types should.
  43. * The class defines a common base type and some common interface for all statically
  44. * derived Scalar Expression classes.
  45. *
  46. * We implement the casts to the statically derived type.
  47. *
  48. * \tparam E an expression type
  49. */
  50. template<class E>
  51. class scalar_expression:
  52. public ublas_expression<E> {
  53. public:
  54. typedef E expression_type;
  55. typedef scalar_tag type_category;
  56. BOOST_UBLAS_INLINE
  57. const expression_type &operator () () const {
  58. return *static_cast<const expression_type *> (this);
  59. }
  60. BOOST_UBLAS_INLINE
  61. expression_type &operator () () {
  62. return *static_cast<expression_type *> (this);
  63. }
  64. };
  65. template<class T>
  66. class scalar_reference:
  67. public scalar_expression<scalar_reference<T> > {
  68. typedef scalar_reference<T> self_type;
  69. public:
  70. typedef T value_type;
  71. typedef const value_type &const_reference;
  72. typedef typename boost::mpl::if_<boost::is_const<T>,
  73. const_reference,
  74. value_type &>::type reference;
  75. typedef const self_type const_closure_type;
  76. typedef const_closure_type closure_type;
  77. // Construction and destruction
  78. BOOST_UBLAS_INLINE
  79. explicit scalar_reference (reference t):
  80. t_ (t) {}
  81. // Conversion
  82. BOOST_UBLAS_INLINE
  83. operator value_type () const {
  84. return t_;
  85. }
  86. // Assignment
  87. BOOST_UBLAS_INLINE
  88. scalar_reference &operator = (const scalar_reference &s) {
  89. t_ = s.t_;
  90. return *this;
  91. }
  92. template<class AE>
  93. BOOST_UBLAS_INLINE
  94. scalar_reference &operator = (const scalar_expression<AE> &ae) {
  95. t_ = ae;
  96. return *this;
  97. }
  98. // Closure comparison
  99. BOOST_UBLAS_INLINE
  100. bool same_closure (const scalar_reference &sr) const {
  101. return &t_ == &sr.t_;
  102. }
  103. private:
  104. reference t_;
  105. };
  106. template<class T>
  107. class scalar_value:
  108. public scalar_expression<scalar_value<T> > {
  109. typedef scalar_value<T> self_type;
  110. public:
  111. typedef T value_type;
  112. typedef const value_type &const_reference;
  113. typedef typename boost::mpl::if_<boost::is_const<T>,
  114. const_reference,
  115. value_type &>::type reference;
  116. typedef const scalar_reference<const self_type> const_closure_type;
  117. typedef scalar_reference<self_type> closure_type;
  118. // Construction and destruction
  119. BOOST_UBLAS_INLINE
  120. scalar_value ():
  121. t_ () {}
  122. BOOST_UBLAS_INLINE
  123. scalar_value (const value_type &t):
  124. t_ (t) {}
  125. BOOST_UBLAS_INLINE
  126. operator value_type () const {
  127. return t_;
  128. }
  129. // Assignment
  130. BOOST_UBLAS_INLINE
  131. scalar_value &operator = (const scalar_value &s) {
  132. t_ = s.t_;
  133. return *this;
  134. }
  135. template<class AE>
  136. BOOST_UBLAS_INLINE
  137. scalar_value &operator = (const scalar_expression<AE> &ae) {
  138. t_ = ae;
  139. return *this;
  140. }
  141. // Closure comparison
  142. BOOST_UBLAS_INLINE
  143. bool same_closure (const scalar_value &sv) const {
  144. return this == &sv; // self closing on instances value
  145. }
  146. private:
  147. value_type t_;
  148. };
  149. /** \brief Base class for Vector Expression models
  150. *
  151. * it does not model the Vector Expression concept but all derived types should.
  152. * The class defines a common base type and some common interface for all
  153. * statically derived Vector Expression classes.
  154. * We implement the casts to the statically derived type.
  155. */
  156. template<class E>
  157. class vector_expression:
  158. public ublas_expression<E> {
  159. public:
  160. static const unsigned complexity = 0;
  161. typedef E expression_type;
  162. typedef vector_tag type_category;
  163. /* E can be an incomplete type - to define the following we would need more template arguments
  164. typedef typename E::size_type size_type;
  165. */
  166. BOOST_UBLAS_INLINE
  167. const expression_type &operator () () const {
  168. return *static_cast<const expression_type *> (this);
  169. }
  170. BOOST_UBLAS_INLINE
  171. expression_type &operator () () {
  172. return *static_cast<expression_type *> (this);
  173. }
  174. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  175. private:
  176. // projection types
  177. typedef vector_range<E> vector_range_type;
  178. typedef vector_range<const E> const_vector_range_type;
  179. typedef vector_slice<E> vector_slice_type;
  180. typedef vector_slice<const E> const_vector_slice_type;
  181. // vector_indirect_type will depend on the A template parameter
  182. typedef basic_range<> default_range; // required to avoid range/slice name confusion
  183. typedef basic_slice<> default_slice;
  184. public:
  185. BOOST_UBLAS_INLINE
  186. const_vector_range_type operator () (const default_range &r) const {
  187. return const_vector_range_type (operator () (), r);
  188. }
  189. BOOST_UBLAS_INLINE
  190. vector_range_type operator () (const default_range &r) {
  191. return vector_range_type (operator () (), r);
  192. }
  193. BOOST_UBLAS_INLINE
  194. const_vector_slice_type operator () (const default_slice &s) const {
  195. return const_vector_slice_type (operator () (), s);
  196. }
  197. BOOST_UBLAS_INLINE
  198. vector_slice_type operator () (const default_slice &s) {
  199. return vector_slice_type (operator () (), s);
  200. }
  201. template<class A>
  202. BOOST_UBLAS_INLINE
  203. const vector_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia) const {
  204. return vector_indirect<const E, indirect_array<A> > (operator () (), ia);
  205. }
  206. template<class A>
  207. BOOST_UBLAS_INLINE
  208. vector_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia) {
  209. return vector_indirect<E, indirect_array<A> > (operator () (), ia);
  210. }
  211. BOOST_UBLAS_INLINE
  212. const_vector_range_type project (const default_range &r) const {
  213. return const_vector_range_type (operator () (), r);
  214. }
  215. BOOST_UBLAS_INLINE
  216. vector_range_type project (const default_range &r) {
  217. return vector_range_type (operator () (), r);
  218. }
  219. BOOST_UBLAS_INLINE
  220. const_vector_slice_type project (const default_slice &s) const {
  221. return const_vector_slice_type (operator () (), s);
  222. }
  223. BOOST_UBLAS_INLINE
  224. vector_slice_type project (const default_slice &s) {
  225. return vector_slice_type (operator () (), s);
  226. }
  227. template<class A>
  228. BOOST_UBLAS_INLINE
  229. const vector_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia) const {
  230. return vector_indirect<const E, indirect_array<A> > (operator () (), ia);
  231. }
  232. template<class A>
  233. BOOST_UBLAS_INLINE
  234. vector_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia) {
  235. return vector_indirect<E, indirect_array<A> > (operator () (), ia);
  236. }
  237. #endif
  238. };
  239. /** \brief Base class for Vector container models
  240. *
  241. * it does not model the Vector concept but all derived types should.
  242. * The class defines a common base type and some common interface for all
  243. * statically derived Vector classes
  244. * We implement the casts to the statically derived type.
  245. */
  246. template<class C>
  247. class vector_container:
  248. public vector_expression<C> {
  249. public:
  250. static const unsigned complexity = 0;
  251. typedef C container_type;
  252. typedef vector_tag type_category;
  253. BOOST_UBLAS_INLINE
  254. const container_type &operator () () const {
  255. return *static_cast<const container_type *> (this);
  256. }
  257. BOOST_UBLAS_INLINE
  258. container_type &operator () () {
  259. return *static_cast<container_type *> (this);
  260. }
  261. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  262. using vector_expression<C>::operator ();
  263. #endif
  264. };
  265. /** \brief Base class for Matrix Expression models
  266. *
  267. * it does not model the Matrix Expression concept but all derived types should.
  268. * The class defines a common base type and some common interface for all
  269. * statically derived Matrix Expression classes
  270. * We implement the casts to the statically derived type.
  271. */
  272. template<class E>
  273. class matrix_expression:
  274. public ublas_expression<E> {
  275. private:
  276. typedef matrix_expression<E> self_type;
  277. public:
  278. static const unsigned complexity = 0;
  279. typedef E expression_type;
  280. typedef matrix_tag type_category;
  281. /* E can be an incomplete type - to define the following we would need more template arguments
  282. typedef typename E::size_type size_type;
  283. */
  284. BOOST_UBLAS_INLINE
  285. const expression_type &operator () () const {
  286. return *static_cast<const expression_type *> (this);
  287. }
  288. BOOST_UBLAS_INLINE
  289. expression_type &operator () () {
  290. return *static_cast<expression_type *> (this);
  291. }
  292. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  293. private:
  294. // projection types
  295. typedef vector_range<E> vector_range_type;
  296. typedef const vector_range<const E> const_vector_range_type;
  297. typedef vector_slice<E> vector_slice_type;
  298. typedef const vector_slice<const E> const_vector_slice_type;
  299. typedef matrix_row<E> matrix_row_type;
  300. typedef const matrix_row<const E> const_matrix_row_type;
  301. typedef matrix_column<E> matrix_column_type;
  302. typedef const matrix_column<const E> const_matrix_column_type;
  303. typedef matrix_range<E> matrix_range_type;
  304. typedef const matrix_range<const E> const_matrix_range_type;
  305. typedef matrix_slice<E> matrix_slice_type;
  306. typedef const matrix_slice<const E> const_matrix_slice_type;
  307. // matrix_indirect_type will depend on the A template parameter
  308. typedef basic_range<> default_range; // required to avoid range/slice name confusion
  309. typedef basic_slice<> default_slice;
  310. public:
  311. BOOST_UBLAS_INLINE
  312. const_matrix_row_type operator [] (std::size_t i) const {
  313. return const_matrix_row_type (operator () (), i);
  314. }
  315. BOOST_UBLAS_INLINE
  316. matrix_row_type operator [] (std::size_t i) {
  317. return matrix_row_type (operator () (), i);
  318. }
  319. BOOST_UBLAS_INLINE
  320. const_matrix_row_type row (std::size_t i) const {
  321. return const_matrix_row_type (operator () (), i);
  322. }
  323. BOOST_UBLAS_INLINE
  324. matrix_row_type row (std::size_t i) {
  325. return matrix_row_type (operator () (), i);
  326. }
  327. BOOST_UBLAS_INLINE
  328. const_matrix_column_type column (std::size_t j) const {
  329. return const_matrix_column_type (operator () (), j);
  330. }
  331. BOOST_UBLAS_INLINE
  332. matrix_column_type column (std::size_t j) {
  333. return matrix_column_type (operator () (), j);
  334. }
  335. BOOST_UBLAS_INLINE
  336. const_matrix_range_type operator () (const default_range &r1, const default_range &r2) const {
  337. return const_matrix_range_type (operator () (), r1, r2);
  338. }
  339. BOOST_UBLAS_INLINE
  340. matrix_range_type operator () (const default_range &r1, const default_range &r2) {
  341. return matrix_range_type (operator () (), r1, r2);
  342. }
  343. BOOST_UBLAS_INLINE
  344. const_matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) const {
  345. return const_matrix_slice_type (operator () (), s1, s2);
  346. }
  347. BOOST_UBLAS_INLINE
  348. matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) {
  349. return matrix_slice_type (operator () (), s1, s2);
  350. }
  351. template<class A>
  352. BOOST_UBLAS_INLINE
  353. const matrix_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const {
  354. return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2);
  355. }
  356. template<class A>
  357. BOOST_UBLAS_INLINE
  358. matrix_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
  359. return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2);
  360. }
  361. BOOST_UBLAS_INLINE
  362. const_matrix_range_type project (const default_range &r1, const default_range &r2) const {
  363. return const_matrix_range_type (operator () (), r1, r2);
  364. }
  365. BOOST_UBLAS_INLINE
  366. matrix_range_type project (const default_range &r1, const default_range &r2) {
  367. return matrix_range_type (operator () (), r1, r2);
  368. }
  369. BOOST_UBLAS_INLINE
  370. const_matrix_slice_type project (const default_slice &s1, const default_slice &s2) const {
  371. return const_matrix_slice_type (operator () (), s1, s2);
  372. }
  373. BOOST_UBLAS_INLINE
  374. matrix_slice_type project (const default_slice &s1, const default_slice &s2) {
  375. return matrix_slice_type (operator () (), s1, s2);
  376. }
  377. template<class A>
  378. BOOST_UBLAS_INLINE
  379. const matrix_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const {
  380. return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2);
  381. }
  382. template<class A>
  383. BOOST_UBLAS_INLINE
  384. matrix_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
  385. return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2);
  386. }
  387. #endif
  388. };
  389. #ifdef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  390. struct iterator1_tag {};
  391. struct iterator2_tag {};
  392. template<class I>
  393. BOOST_UBLAS_INLINE
  394. typename I::dual_iterator_type begin (const I &it, iterator1_tag) {
  395. return it ().find2 (1, it.index1 (), 0);
  396. }
  397. template<class I>
  398. BOOST_UBLAS_INLINE
  399. typename I::dual_iterator_type end (const I &it, iterator1_tag) {
  400. return it ().find2 (1, it.index1 (), it ().size2 ());
  401. }
  402. template<class I>
  403. BOOST_UBLAS_INLINE
  404. typename I::dual_reverse_iterator_type rbegin (const I &it, iterator1_tag) {
  405. return typename I::dual_reverse_iterator_type (end (it, iterator1_tag ()));
  406. }
  407. template<class I>
  408. BOOST_UBLAS_INLINE
  409. typename I::dual_reverse_iterator_type rend (const I &it, iterator1_tag) {
  410. return typename I::dual_reverse_iterator_type (begin (it, iterator1_tag ()));
  411. }
  412. template<class I>
  413. BOOST_UBLAS_INLINE
  414. typename I::dual_iterator_type begin (const I &it, iterator2_tag) {
  415. return it ().find1 (1, 0, it.index2 ());
  416. }
  417. template<class I>
  418. BOOST_UBLAS_INLINE
  419. typename I::dual_iterator_type end (const I &it, iterator2_tag) {
  420. return it ().find1 (1, it ().size1 (), it.index2 ());
  421. }
  422. template<class I>
  423. BOOST_UBLAS_INLINE
  424. typename I::dual_reverse_iterator_type rbegin (const I &it, iterator2_tag) {
  425. return typename I::dual_reverse_iterator_type (end (it, iterator2_tag ()));
  426. }
  427. template<class I>
  428. BOOST_UBLAS_INLINE
  429. typename I::dual_reverse_iterator_type rend (const I &it, iterator2_tag) {
  430. return typename I::dual_reverse_iterator_type (begin (it, iterator2_tag ()));
  431. }
  432. #endif
  433. /** \brief Base class for Matrix container models
  434. *
  435. * it does not model the Matrix concept but all derived types should.
  436. * The class defines a common base type and some common interface for all
  437. * statically derived Matrix classes
  438. * We implement the casts to the statically derived type.
  439. */
  440. template<class C>
  441. class matrix_container:
  442. public matrix_expression<C> {
  443. public:
  444. static const unsigned complexity = 0;
  445. typedef C container_type;
  446. typedef matrix_tag type_category;
  447. BOOST_UBLAS_INLINE
  448. const container_type &operator () () const {
  449. return *static_cast<const container_type *> (this);
  450. }
  451. BOOST_UBLAS_INLINE
  452. container_type &operator () () {
  453. return *static_cast<container_type *> (this);
  454. }
  455. #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  456. using matrix_expression<C>::operator ();
  457. #endif
  458. };
  459. }}}
  460. #endif