1 // Copyright (c) 2000-2013
2 // Joerg Walter, Mathias Koch. David Bellot
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)
8 // The authors gratefully acknowledge the support of
9 // GeNeSys mbH & Co. KG in producing this work.
11 #ifndef _BOOST_UBLAS_EXPRESSION_TYPE_
12 #define _BOOST_UBLAS_EXPRESSION_TYPE_
14 #include <boost/numeric/ublas/exception.hpp>
15 #include <boost/numeric/ublas/traits.hpp>
16 #include <boost/numeric/ublas/functional.hpp>
19 // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
20 // Iterators based on ideas of Jeremy Siek
22 namespace boost { namespace numeric { namespace ublas {
24 /** \brief Base class for uBLAS statically derived expressions using the the Barton Nackman trick
26 * This is a NonAssignable class
27 * Directly implement nonassignable - simplifes debugging call trace!
29 * \tparam E an expression type
32 class ublas_expression {
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;
41 ublas_expression () {}
42 ~ublas_expression () {}
44 const ublas_expression& operator= (const ublas_expression &);
48 /** \brief Base class for Scalar Expression models
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.
54 * We implement the casts to the statically derived type.
56 * \tparam E an expression type
59 class scalar_expression:
60 public ublas_expression<E> {
62 typedef E expression_type;
63 typedef scalar_tag type_category;
66 const expression_type &operator () () const {
67 return *static_cast<const expression_type *> (this);
70 expression_type &operator () () {
71 return *static_cast<expression_type *> (this);
76 class scalar_reference:
77 public scalar_expression<scalar_reference<T> > {
79 typedef scalar_reference<T> self_type;
82 typedef const value_type &const_reference;
83 typedef typename boost::mpl::if_<boost::is_const<T>,
85 value_type &>::type reference;
86 typedef const self_type const_closure_type;
87 typedef const_closure_type closure_type;
89 // Construction and destruction
91 explicit scalar_reference (reference t):
96 operator value_type () const {
102 scalar_reference &operator = (const scalar_reference &s) {
108 scalar_reference &operator = (const scalar_expression<AE> &ae) {
113 // Closure comparison
115 bool same_closure (const scalar_reference &sr) const {
116 return &t_ == &sr.t_;
125 public scalar_expression<scalar_value<T> > {
127 typedef scalar_value<T> self_type;
129 typedef T value_type;
130 typedef const value_type &const_reference;
131 typedef typename boost::mpl::if_<boost::is_const<T>,
133 value_type &>::type reference;
134 typedef const scalar_reference<const self_type> const_closure_type;
135 typedef scalar_reference<self_type> closure_type;
137 // Construction and destruction
142 scalar_value (const value_type &t):
146 operator value_type () const {
152 scalar_value &operator = (const scalar_value &s) {
158 scalar_value &operator = (const scalar_expression<AE> &ae) {
163 // Closure comparison
165 bool same_closure (const scalar_value &sv) const {
166 return this == &sv; // self closing on instances value
174 /** \brief Base class for Vector Expression models
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.
182 class vector_expression:
183 public ublas_expression<E> {
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;
193 const expression_type &operator () () const {
194 return *static_cast<const expression_type *> (this);
197 expression_type &operator () () {
198 return *static_cast<expression_type *> (this);
201 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
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;
213 const_vector_range_type operator () (const default_range &r) const {
214 return const_vector_range_type (operator () (), r);
217 vector_range_type operator () (const default_range &r) {
218 return vector_range_type (operator () (), r);
221 const_vector_slice_type operator () (const default_slice &s) const {
222 return const_vector_slice_type (operator () (), s);
225 vector_slice_type operator () (const default_slice &s) {
226 return vector_slice_type (operator () (), s);
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);
235 vector_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia) {
236 return vector_indirect<E, indirect_array<A> > (operator () (), ia);
240 const_vector_range_type project (const default_range &r) const {
241 return const_vector_range_type (operator () (), r);
244 vector_range_type project (const default_range &r) {
245 return vector_range_type (operator () (), r);
248 const_vector_slice_type project (const default_slice &s) const {
249 return const_vector_slice_type (operator () (), s);
252 vector_slice_type project (const default_slice &s) {
253 return vector_slice_type (operator () (), s);
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);
262 vector_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia) {
263 return vector_indirect<E, indirect_array<A> > (operator () (), ia);
268 /** \brief Base class for Vector container models
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.
276 class vector_container:
277 public vector_expression<C> {
279 static const unsigned complexity = 0;
280 typedef C container_type;
281 typedef vector_tag type_category;
284 const container_type &operator () () const {
285 return *static_cast<const container_type *> (this);
288 container_type &operator () () {
289 return *static_cast<container_type *> (this);
292 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
293 using vector_expression<C>::operator ();
298 /** \brief Base class for Matrix Expression models
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.
306 class matrix_expression:
307 public ublas_expression<E> {
309 typedef matrix_expression<E> self_type;
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;
319 const expression_type &operator () () const {
320 return *static_cast<const expression_type *> (this);
323 expression_type &operator () () {
324 return *static_cast<expression_type *> (this);
327 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
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;
348 const_matrix_row_type operator [] (std::size_t i) const {
349 return const_matrix_row_type (operator () (), i);
352 matrix_row_type operator [] (std::size_t i) {
353 return matrix_row_type (operator () (), i);
356 const_matrix_row_type row (std::size_t i) const {
357 return const_matrix_row_type (operator () (), i);
360 matrix_row_type row (std::size_t i) {
361 return matrix_row_type (operator () (), i);
364 const_matrix_column_type column (std::size_t j) const {
365 return const_matrix_column_type (operator () (), j);
368 matrix_column_type column (std::size_t j) {
369 return matrix_column_type (operator () (), j);
373 const_matrix_range_type operator () (const default_range &r1, const default_range &r2) const {
374 return const_matrix_range_type (operator () (), r1, r2);
377 matrix_range_type operator () (const default_range &r1, const default_range &r2) {
378 return matrix_range_type (operator () (), r1, r2);
381 const_matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) const {
382 return const_matrix_slice_type (operator () (), s1, s2);
385 matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) {
386 return matrix_slice_type (operator () (), s1, s2);
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);
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);
400 const_matrix_range_type project (const default_range &r1, const default_range &r2) const {
401 return const_matrix_range_type (operator () (), r1, r2);
404 matrix_range_type project (const default_range &r1, const default_range &r2) {
405 return matrix_range_type (operator () (), r1, r2);
408 const_matrix_slice_type project (const default_slice &s1, const default_slice &s2) const {
409 return const_matrix_slice_type (operator () (), s1, s2);
412 matrix_slice_type project (const default_slice &s1, const default_slice &s2) {
413 return matrix_slice_type (operator () (), s1, s2);
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);
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);
428 #ifdef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
429 struct iterator1_tag {};
430 struct iterator2_tag {};
434 typename I::dual_iterator_type begin (const I &it, iterator1_tag) {
435 return it ().find2 (1, it.index1 (), 0);
439 typename I::dual_iterator_type end (const I &it, iterator1_tag) {
440 return it ().find2 (1, it.index1 (), it ().size2 ());
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 ()));
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 ()));
455 typename I::dual_iterator_type begin (const I &it, iterator2_tag) {
456 return it ().find1 (1, 0, it.index2 ());
460 typename I::dual_iterator_type end (const I &it, iterator2_tag) {
461 return it ().find1 (1, it ().size1 (), it.index2 ());
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 ()));
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 ()));
475 /** \brief Base class for Matrix container models
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.
483 class matrix_container:
484 public matrix_expression<C> {
486 static const unsigned complexity = 0;
487 typedef C container_type;
488 typedef matrix_tag type_category;
491 const container_type &operator () () const {
492 return *static_cast<const container_type *> (this);
495 container_type &operator () () {
496 return *static_cast<container_type *> (this);
499 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
500 using matrix_expression<C>::operator ();