fix doc example typo
[boost.git] / boost / numeric / ublas / expression_types.hpp
blob86241a9f84765d04acf00904d5895bc236aeeea9
1 //
2 // Copyright (c) 2000-2002
3 // Joerg Walter, Mathias Koch
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.
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 // Base class for uBLAS staticaly derived expressions - see the Barton Nackman trick
26 // Provides numeric properties for linear algebra
27 template<class E>
28 class ublas_expression {
29 public:
30 typedef E expression_type;
31 /* E can be an incomplete type - to define the following we would need more template arguments
32 typedef typename E::type_category type_category;
33 typedef typename E::value_type value_type;
36 // Directly implement nonassignable - simplifes debugging call trace!
37 protected:
38 ublas_expression () {}
39 ~ublas_expression () {}
40 private:
41 const ublas_expression& operator= (const ublas_expression &);
45 // Base class for Scalar Expression models -
46 // it does not model the Scalar Expression concept but all derived types should.
47 // The class defines a common base type and some common interface for all
48 // statically derived Scalar Expression classes
49 // We implement the casts to the statically derived type.
50 template<class E>
51 class scalar_expression:
52 public ublas_expression<E> {
53 public:
54 typedef E expression_type;
55 typedef scalar_tag type_category;
57 BOOST_UBLAS_INLINE
58 const expression_type &operator () () const {
59 return *static_cast<const expression_type *> (this);
61 BOOST_UBLAS_INLINE
62 expression_type &operator () () {
63 return *static_cast<expression_type *> (this);
67 template<class T>
68 class scalar_reference:
69 public scalar_expression<scalar_reference<T> > {
71 typedef scalar_reference<T> self_type;
72 public:
73 typedef T value_type;
74 typedef const value_type &const_reference;
75 typedef typename boost::mpl::if_<boost::is_const<T>,
76 const_reference,
77 value_type &>::type reference;
78 typedef const self_type const_closure_type;
79 typedef const_closure_type closure_type;
81 // Construction and destruction
82 BOOST_UBLAS_INLINE
83 explicit scalar_reference (reference t):
84 t_ (t) {}
86 // Conversion
87 BOOST_UBLAS_INLINE
88 operator value_type () const {
89 return t_;
92 // Assignment
93 BOOST_UBLAS_INLINE
94 scalar_reference &operator = (const scalar_reference &s) {
95 t_ = s.t_;
96 return *this;
98 template<class AE>
99 BOOST_UBLAS_INLINE
100 scalar_reference &operator = (const scalar_expression<AE> &ae) {
101 t_ = ae;
102 return *this;
105 // Closure comparison
106 BOOST_UBLAS_INLINE
107 bool same_closure (const scalar_reference &sr) const {
108 return &t_ == &sr.t_;
111 private:
112 reference t_;
115 template<class T>
116 class scalar_value:
117 public scalar_expression<scalar_value<T> > {
119 typedef scalar_value<T> self_type;
120 public:
121 typedef T value_type;
122 typedef const value_type &const_reference;
123 typedef typename boost::mpl::if_<boost::is_const<T>,
124 const_reference,
125 value_type &>::type reference;
126 typedef const scalar_reference<const self_type> const_closure_type;
127 typedef scalar_reference<self_type> closure_type;
129 // Construction and destruction
130 BOOST_UBLAS_INLINE
131 scalar_value ():
132 t_ () {}
133 BOOST_UBLAS_INLINE
134 scalar_value (const value_type &t):
135 t_ (t) {}
137 BOOST_UBLAS_INLINE
138 operator value_type () const {
139 return t_;
142 // Assignment
143 BOOST_UBLAS_INLINE
144 scalar_value &operator = (const scalar_value &s) {
145 t_ = s.t_;
146 return *this;
148 template<class AE>
149 BOOST_UBLAS_INLINE
150 scalar_value &operator = (const scalar_expression<AE> &ae) {
151 t_ = ae;
152 return *this;
155 // Closure comparison
156 BOOST_UBLAS_INLINE
157 bool same_closure (const scalar_value &sv) const {
158 return this == &sv; // self closing on instances value
161 private:
162 value_type t_;
166 // Base class for Vector Expression models -
167 // it does not model the Vector Expression concept but all derived types should.
168 // The class defines a common base type and some common interface for all
169 // statically derived Vector Expression classes
170 // We implement the casts to the statically derived type.
171 template<class E>
172 class vector_expression:
173 public ublas_expression<E> {
174 public:
175 static const unsigned complexity = 0;
176 typedef E expression_type;
177 typedef vector_tag type_category;
178 /* E can be an incomplete type - to define the following we would need more template arguments
179 typedef typename E::size_type size_type;
182 BOOST_UBLAS_INLINE
183 const expression_type &operator () () const {
184 return *static_cast<const expression_type *> (this);
186 BOOST_UBLAS_INLINE
187 expression_type &operator () () {
188 return *static_cast<expression_type *> (this);
191 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
192 private:
193 // projection types
194 typedef vector_range<E> vector_range_type;
195 typedef vector_range<const E> const_vector_range_type;
196 typedef vector_slice<E> vector_slice_type;
197 typedef vector_slice<const E> const_vector_slice_type;
198 // vector_indirect_type will depend on the A template parameter
199 typedef basic_range<> default_range; // required to avoid range/slice name confusion
200 typedef basic_slice<> default_slice;
201 public:
202 BOOST_UBLAS_INLINE
203 const_vector_range_type operator () (const default_range &r) const {
204 return const_vector_range_type (operator () (), r);
206 BOOST_UBLAS_INLINE
207 vector_range_type operator () (const default_range &r) {
208 return vector_range_type (operator () (), r);
210 BOOST_UBLAS_INLINE
211 const_vector_slice_type operator () (const default_slice &s) const {
212 return const_vector_slice_type (operator () (), s);
214 BOOST_UBLAS_INLINE
215 vector_slice_type operator () (const default_slice &s) {
216 return vector_slice_type (operator () (), s);
218 template<class A>
219 BOOST_UBLAS_INLINE
220 const vector_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia) const {
221 return vector_indirect<const E, indirect_array<A> > (operator () (), ia);
223 template<class A>
224 BOOST_UBLAS_INLINE
225 vector_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia) {
226 return vector_indirect<E, indirect_array<A> > (operator () (), ia);
229 BOOST_UBLAS_INLINE
230 const_vector_range_type project (const default_range &r) const {
231 return const_vector_range_type (operator () (), r);
233 BOOST_UBLAS_INLINE
234 vector_range_type project (const default_range &r) {
235 return vector_range_type (operator () (), r);
237 BOOST_UBLAS_INLINE
238 const_vector_slice_type project (const default_slice &s) const {
239 return const_vector_slice_type (operator () (), s);
241 BOOST_UBLAS_INLINE
242 vector_slice_type project (const default_slice &s) {
243 return vector_slice_type (operator () (), s);
245 template<class A>
246 BOOST_UBLAS_INLINE
247 const vector_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia) const {
248 return vector_indirect<const E, indirect_array<A> > (operator () (), ia);
250 template<class A>
251 BOOST_UBLAS_INLINE
252 vector_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia) {
253 return vector_indirect<E, indirect_array<A> > (operator () (), ia);
255 #endif
258 // Base class for Vector container models -
259 // it does not model the Vector concept but all derived types should.
260 // The class defines a common base type and some common interface for all
261 // statically derived Vector classes
262 // We implement the casts to the statically derived type.
263 template<class C>
264 class vector_container:
265 public vector_expression<C> {
266 public:
267 static const unsigned complexity = 0;
268 typedef C container_type;
269 typedef vector_tag type_category;
271 BOOST_UBLAS_INLINE
272 const container_type &operator () () const {
273 return *static_cast<const container_type *> (this);
275 BOOST_UBLAS_INLINE
276 container_type &operator () () {
277 return *static_cast<container_type *> (this);
280 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
281 using vector_expression<C>::operator ();
282 #endif
286 // Base class for Matrix Expression models -
287 // it does not model the Matrix Expression concept but all derived types should.
288 // The class defines a common base type and some common interface for all
289 // statically derived Matrix Expression classes
290 // We implement the casts to the statically derived type.
291 template<class E>
292 class matrix_expression:
293 public ublas_expression<E> {
294 private:
295 typedef matrix_expression<E> self_type;
296 public:
297 static const unsigned complexity = 0;
298 typedef E expression_type;
299 typedef matrix_tag type_category;
300 /* E can be an incomplete type - to define the following we would need more template arguments
301 typedef typename E::size_type size_type;
304 BOOST_UBLAS_INLINE
305 const expression_type &operator () () const {
306 return *static_cast<const expression_type *> (this);
308 BOOST_UBLAS_INLINE
309 expression_type &operator () () {
310 return *static_cast<expression_type *> (this);
313 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
314 private:
315 // projection types
316 typedef vector_range<E> vector_range_type;
317 typedef const vector_range<const E> const_vector_range_type;
318 typedef vector_slice<E> vector_slice_type;
319 typedef const vector_slice<const E> const_vector_slice_type;
320 typedef matrix_row<E> matrix_row_type;
321 typedef const matrix_row<const E> const_matrix_row_type;
322 typedef matrix_column<E> matrix_column_type;
323 typedef const matrix_column<const E> const_matrix_column_type;
324 typedef matrix_range<E> matrix_range_type;
325 typedef const matrix_range<const E> const_matrix_range_type;
326 typedef matrix_slice<E> matrix_slice_type;
327 typedef const matrix_slice<const E> const_matrix_slice_type;
328 // matrix_indirect_type will depend on the A template parameter
329 typedef basic_range<> default_range; // required to avoid range/slice name confusion
330 typedef basic_slice<> default_slice;
332 public:
333 BOOST_UBLAS_INLINE
334 const_matrix_row_type operator [] (std::size_t i) const {
335 return const_matrix_row_type (operator () (), i);
337 BOOST_UBLAS_INLINE
338 matrix_row_type operator [] (std::size_t i) {
339 return matrix_row_type (operator () (), i);
341 BOOST_UBLAS_INLINE
342 const_matrix_row_type row (std::size_t i) const {
343 return const_matrix_row_type (operator () (), i);
345 BOOST_UBLAS_INLINE
346 matrix_row_type row (std::size_t i) {
347 return matrix_row_type (operator () (), i);
349 BOOST_UBLAS_INLINE
350 const_matrix_column_type column (std::size_t j) const {
351 return const_matrix_column_type (operator () (), j);
353 BOOST_UBLAS_INLINE
354 matrix_column_type column (std::size_t j) {
355 return matrix_column_type (operator () (), j);
358 BOOST_UBLAS_INLINE
359 const_matrix_range_type operator () (const default_range &r1, const default_range &r2) const {
360 return const_matrix_range_type (operator () (), r1, r2);
362 BOOST_UBLAS_INLINE
363 matrix_range_type operator () (const default_range &r1, const default_range &r2) {
364 return matrix_range_type (operator () (), r1, r2);
366 BOOST_UBLAS_INLINE
367 const_matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) const {
368 return const_matrix_slice_type (operator () (), s1, s2);
370 BOOST_UBLAS_INLINE
371 matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) {
372 return matrix_slice_type (operator () (), s1, s2);
374 template<class A>
375 BOOST_UBLAS_INLINE
376 const matrix_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const {
377 return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2);
379 template<class A>
380 BOOST_UBLAS_INLINE
381 matrix_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
382 return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2);
385 BOOST_UBLAS_INLINE
386 const_matrix_range_type project (const default_range &r1, const default_range &r2) const {
387 return const_matrix_range_type (operator () (), r1, r2);
389 BOOST_UBLAS_INLINE
390 matrix_range_type project (const default_range &r1, const default_range &r2) {
391 return matrix_range_type (operator () (), r1, r2);
393 BOOST_UBLAS_INLINE
394 const_matrix_slice_type project (const default_slice &s1, const default_slice &s2) const {
395 return const_matrix_slice_type (operator () (), s1, s2);
397 BOOST_UBLAS_INLINE
398 matrix_slice_type project (const default_slice &s1, const default_slice &s2) {
399 return matrix_slice_type (operator () (), s1, s2);
401 template<class A>
402 BOOST_UBLAS_INLINE
403 const matrix_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const {
404 return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2);
406 template<class A>
407 BOOST_UBLAS_INLINE
408 matrix_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
409 return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2);
411 #endif
414 #ifdef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
415 struct iterator1_tag {};
416 struct iterator2_tag {};
418 template<class I>
419 BOOST_UBLAS_INLINE
420 typename I::dual_iterator_type begin (const I &it, iterator1_tag) {
421 return it ().find2 (1, it.index1 (), 0);
423 template<class I>
424 BOOST_UBLAS_INLINE
425 typename I::dual_iterator_type end (const I &it, iterator1_tag) {
426 return it ().find2 (1, it.index1 (), it ().size2 ());
428 template<class I>
429 BOOST_UBLAS_INLINE
430 typename I::dual_reverse_iterator_type rbegin (const I &it, iterator1_tag) {
431 return typename I::dual_reverse_iterator_type (end (it, iterator1_tag ()));
433 template<class I>
434 BOOST_UBLAS_INLINE
435 typename I::dual_reverse_iterator_type rend (const I &it, iterator1_tag) {
436 return typename I::dual_reverse_iterator_type (begin (it, iterator1_tag ()));
439 template<class I>
440 BOOST_UBLAS_INLINE
441 typename I::dual_iterator_type begin (const I &it, iterator2_tag) {
442 return it ().find1 (1, 0, it.index2 ());
444 template<class I>
445 BOOST_UBLAS_INLINE
446 typename I::dual_iterator_type end (const I &it, iterator2_tag) {
447 return it ().find1 (1, it ().size1 (), it.index2 ());
449 template<class I>
450 BOOST_UBLAS_INLINE
451 typename I::dual_reverse_iterator_type rbegin (const I &it, iterator2_tag) {
452 return typename I::dual_reverse_iterator_type (end (it, iterator2_tag ()));
454 template<class I>
455 BOOST_UBLAS_INLINE
456 typename I::dual_reverse_iterator_type rend (const I &it, iterator2_tag) {
457 return typename I::dual_reverse_iterator_type (begin (it, iterator2_tag ()));
459 #endif
461 // Base class for Matrix container models -
462 // it does not model the Matrix concept but all derived types should.
463 // The class defines a common base type and some common interface for all
464 // statically derived Matrix classes
465 // We implement the casts to the statically derived type.
466 template<class C>
467 class matrix_container:
468 public matrix_expression<C> {
469 public:
470 static const unsigned complexity = 0;
471 typedef C container_type;
472 typedef matrix_tag type_category;
474 BOOST_UBLAS_INLINE
475 const container_type &operator () () const {
476 return *static_cast<const container_type *> (this);
478 BOOST_UBLAS_INLINE
479 container_type &operator () () {
480 return *static_cast<container_type *> (this);
483 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
484 using matrix_expression<C>::operator ();
485 #endif
490 #endif