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