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
22namespace 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

source code of include/boost/numeric/ublas/expression_types.hpp