2 // Copyright (c) 2000-2010
3 // Joerg Walter, Mathias Koch. David Bellot
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)
9 // The authors gratefully acknowledge the support of
10 // GeNeSys mbH & Co. KG in producing this work.
12 #ifndef _BOOST_UBLAS_EXPRESSION_TYPE_
13 #define _BOOST_UBLAS_EXPRESSION_TYPE_
15 #include <boost/numeric/ublas/exception.hpp>
16 #include <boost/numeric/ublas/traits.hpp>
17 #include <boost/numeric/ublas/functional.hpp>
20 // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
21 // Iterators based on ideas of Jeremy Siek
23 namespace boost { namespace numeric { namespace ublas {
25 /** \brief Base class for uBLAS statically derived expressions using the the Barton Nackman trick
27 * This is a NonAssignable class
28 * Directly implement nonassignable - simplifes debugging call trace!
30 * \tparam E an expression type
33 class ublas_expression {
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;
42 ublas_expression () {}
43 ~ublas_expression () {}
45 const ublas_expression& operator= (const ublas_expression &);
49 /** \brief Base class for Scalar Expression models
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.
55 * We implement the casts to the statically derived type.
57 * \tparam E an expression type
60 class scalar_expression:
61 public ublas_expression<E> {
63 typedef E expression_type;
64 typedef scalar_tag type_category;
67 const expression_type &operator () () const {
68 return *static_cast<const expression_type *> (this);
71 expression_type &operator () () {
72 return *static_cast<expression_type *> (this);
77 class scalar_reference:
78 public scalar_expression<scalar_reference<T> > {
80 typedef scalar_reference<T> self_type;
83 typedef const value_type &const_reference;
84 typedef typename boost::mpl::if_<boost::is_const<T>,
86 value_type &>::type reference;
87 typedef const self_type const_closure_type;
88 typedef const_closure_type closure_type;
90 // Construction and destruction
92 explicit scalar_reference (reference t):
97 operator value_type () const {
103 scalar_reference &operator = (const scalar_reference &s) {
109 scalar_reference &operator = (const scalar_expression<AE> &ae) {
114 // Closure comparison
116 bool same_closure (const scalar_reference &sr) const {
117 return &t_ == &sr.t_;
126 public scalar_expression<scalar_value<T> > {
128 typedef scalar_value<T> self_type;
130 typedef T value_type;
131 typedef const value_type &const_reference;
132 typedef typename boost::mpl::if_<boost::is_const<T>,
134 value_type &>::type reference;
135 typedef const scalar_reference<const self_type> const_closure_type;
136 typedef scalar_reference<self_type> closure_type;
138 // Construction and destruction
143 scalar_value (const value_type &t):
147 operator value_type () const {
153 scalar_value &operator = (const scalar_value &s) {
159 scalar_value &operator = (const scalar_expression<AE> &ae) {
164 // Closure comparison
166 bool same_closure (const scalar_value &sv) const {
167 return this == &sv; // self closing on instances value
175 /** \brief Base class for Vector Expression models
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.
183 class vector_expression:
184 public ublas_expression<E> {
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;
194 const expression_type &operator () () const {
195 return *static_cast<const expression_type *> (this);
198 expression_type &operator () () {
199 return *static_cast<expression_type *> (this);
202 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
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;
214 const_vector_range_type operator () (const default_range &r) const {
215 return const_vector_range_type (operator () (), r);
218 vector_range_type operator () (const default_range &r) {
219 return vector_range_type (operator () (), r);
222 const_vector_slice_type operator () (const default_slice &s) const {
223 return const_vector_slice_type (operator () (), s);
226 vector_slice_type operator () (const default_slice &s) {
227 return vector_slice_type (operator () (), s);
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);
236 vector_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia) {
237 return vector_indirect<E, indirect_array<A> > (operator () (), ia);
241 const_vector_range_type project (const default_range &r) const {
242 return const_vector_range_type (operator () (), r);
245 vector_range_type project (const default_range &r) {
246 return vector_range_type (operator () (), r);
249 const_vector_slice_type project (const default_slice &s) const {
250 return const_vector_slice_type (operator () (), s);
253 vector_slice_type project (const default_slice &s) {
254 return vector_slice_type (operator () (), s);
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);
263 vector_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia) {
264 return vector_indirect<E, indirect_array<A> > (operator () (), ia);
269 /** \brief Base class for Vector container models
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.
277 class vector_container:
278 public vector_expression<C> {
280 static const unsigned complexity = 0;
281 typedef C container_type;
282 typedef vector_tag type_category;
285 const container_type &operator () () const {
286 return *static_cast<const container_type *> (this);
289 container_type &operator () () {
290 return *static_cast<container_type *> (this);
293 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
294 using vector_expression<C>::operator ();
299 /** \brief Base class for Matrix Expression models
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.
307 class matrix_expression:
308 public ublas_expression<E> {
310 typedef matrix_expression<E> self_type;
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;
320 const expression_type &operator () () const {
321 return *static_cast<const expression_type *> (this);
324 expression_type &operator () () {
325 return *static_cast<expression_type *> (this);
328 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
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;
349 const_matrix_row_type operator [] (std::size_t i) const {
350 return const_matrix_row_type (operator () (), i);
353 matrix_row_type operator [] (std::size_t i) {
354 return matrix_row_type (operator () (), i);
357 const_matrix_row_type row (std::size_t i) const {
358 return const_matrix_row_type (operator () (), i);
361 matrix_row_type row (std::size_t i) {
362 return matrix_row_type (operator () (), i);
365 const_matrix_column_type column (std::size_t j) const {
366 return const_matrix_column_type (operator () (), j);
369 matrix_column_type column (std::size_t j) {
370 return matrix_column_type (operator () (), j);
374 const_matrix_range_type operator () (const default_range &r1, const default_range &r2) const {
375 return const_matrix_range_type (operator () (), r1, r2);
378 matrix_range_type operator () (const default_range &r1, const default_range &r2) {
379 return matrix_range_type (operator () (), r1, r2);
382 const_matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) const {
383 return const_matrix_slice_type (operator () (), s1, s2);
386 matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) {
387 return matrix_slice_type (operator () (), s1, s2);
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);
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);
401 const_matrix_range_type project (const default_range &r1, const default_range &r2) const {
402 return const_matrix_range_type (operator () (), r1, r2);
405 matrix_range_type project (const default_range &r1, const default_range &r2) {
406 return matrix_range_type (operator () (), r1, r2);
409 const_matrix_slice_type project (const default_slice &s1, const default_slice &s2) const {
410 return const_matrix_slice_type (operator () (), s1, s2);
413 matrix_slice_type project (const default_slice &s1, const default_slice &s2) {
414 return matrix_slice_type (operator () (), s1, s2);
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);
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);
429 #ifdef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
430 struct iterator1_tag {};
431 struct iterator2_tag {};
435 typename I::dual_iterator_type begin (const I &it, iterator1_tag) {
436 return it ().find2 (1, it.index1 (), 0);
440 typename I::dual_iterator_type end (const I &it, iterator1_tag) {
441 return it ().find2 (1, it.index1 (), it ().size2 ());
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 ()));
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 ()));
456 typename I::dual_iterator_type begin (const I &it, iterator2_tag) {
457 return it ().find1 (1, 0, it.index2 ());
461 typename I::dual_iterator_type end (const I &it, iterator2_tag) {
462 return it ().find1 (1, it ().size1 (), it.index2 ());
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 ()));
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 ()));
476 /** \brief Base class for Matrix container models
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.
484 class matrix_container:
485 public matrix_expression<C> {
487 static const unsigned complexity = 0;
488 typedef C container_type;
489 typedef matrix_tag type_category;
492 const container_type &operator () () const {
493 return *static_cast<const container_type *> (this);
496 container_type &operator () () {
497 return *static_cast<container_type *> (this);
500 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
501 using matrix_expression<C>::operator ();