]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 |