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