Boost.uBlas 1.49
Linear Algebra in C++: matrices, vectors and numeric algorithms

expression_types.hpp

Go to the documentation of this file.
00001 //
00002 //  Copyright (c) 2000-2010
00003 //  Joerg Walter, Mathias Koch. David Bellot
00004 //
00005 //  Distributed under the Boost Software License, Version 1.0. (See
00006 //  accompanying file LICENSE_1_0.txt or copy at
00007 //  http://www.boost.org/LICENSE_1_0.txt)
00008 //
00009 //  The authors gratefully acknowledge the support of
00010 //  GeNeSys mbH & Co. KG in producing this work.
00011 //
00012 #ifndef _BOOST_UBLAS_EXPRESSION_TYPE_
00013 #define _BOOST_UBLAS_EXPRESSION_TYPE_
00014 
00015 #include <boost/numeric/ublas/exception.hpp>
00016 #include <boost/numeric/ublas/traits.hpp>
00017 #include <boost/numeric/ublas/functional.hpp>
00018 
00019 
00020 // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
00021 // Iterators based on ideas of Jeremy Siek
00022 
00023 namespace boost { namespace numeric { namespace ublas {
00024 
00032     template<class E>
00033     class ublas_expression {
00034     public:
00035         typedef E expression_type;
00036         /* E can be an incomplete type - to define the following we would need more template arguments
00037         typedef typename E::type_category type_category;
00038         typedef typename E::value_type value_type;
00039         */
00040         
00041     protected:
00042         ublas_expression () {}
00043         ~ublas_expression () {}
00044     private:
00045         const ublas_expression& operator= (const ublas_expression &);
00046     };
00047 
00048 
00059     template<class E>
00060     class scalar_expression:
00061         public ublas_expression<E> {
00062     public:
00063         typedef E expression_type;
00064         typedef scalar_tag type_category;
00065 
00066         BOOST_UBLAS_INLINE
00067         const expression_type &operator () () const {
00068             return *static_cast<const expression_type *> (this);
00069         }
00070         BOOST_UBLAS_INLINE
00071         expression_type &operator () () {
00072             return *static_cast<expression_type *> (this);
00073         }
00074     };
00075 
00076     template<class T>
00077     class scalar_reference:
00078         public scalar_expression<scalar_reference<T> > {
00079 
00080         typedef scalar_reference<T> self_type;
00081     public:
00082         typedef T value_type;
00083         typedef const value_type &const_reference;
00084         typedef typename boost::mpl::if_<boost::is_const<T>,
00085                                           const_reference,
00086                                           value_type &>::type reference;
00087         typedef const self_type const_closure_type;
00088         typedef const_closure_type closure_type;
00089 
00090         // Construction and destruction
00091         BOOST_UBLAS_INLINE
00092         explicit scalar_reference (reference t):
00093             t_ (t) {}
00094 
00095         // Conversion
00096         BOOST_UBLAS_INLINE
00097         operator value_type () const {
00098             return t_;
00099         }
00100 
00101         // Assignment
00102         BOOST_UBLAS_INLINE
00103         scalar_reference &operator = (const scalar_reference &s) {
00104             t_ = s.t_;
00105             return *this;
00106         }
00107         template<class AE>
00108         BOOST_UBLAS_INLINE
00109         scalar_reference &operator = (const scalar_expression<AE> &ae) {
00110             t_ = ae;
00111             return *this;
00112         }
00113 
00114         // Closure comparison
00115         BOOST_UBLAS_INLINE
00116         bool same_closure (const scalar_reference &sr) const {
00117             return &t_ == &sr.t_;
00118         }
00119 
00120     private:
00121         reference t_;
00122     };
00123 
00124     template<class T>
00125     class scalar_value:
00126         public scalar_expression<scalar_value<T> > {
00127 
00128         typedef scalar_value<T> self_type;
00129     public:
00130         typedef T value_type;
00131         typedef const value_type &const_reference;
00132         typedef typename boost::mpl::if_<boost::is_const<T>,
00133                                           const_reference,
00134                                           value_type &>::type reference;
00135         typedef const scalar_reference<const self_type> const_closure_type;
00136         typedef scalar_reference<self_type> closure_type;
00137 
00138         // Construction and destruction
00139         BOOST_UBLAS_INLINE
00140         scalar_value ():
00141             t_ () {}
00142         BOOST_UBLAS_INLINE
00143         scalar_value (const value_type &t):
00144             t_ (t) {}
00145 
00146         BOOST_UBLAS_INLINE
00147         operator value_type () const {
00148             return t_;
00149         }
00150 
00151         // Assignment
00152         BOOST_UBLAS_INLINE
00153         scalar_value &operator = (const scalar_value &s) {
00154             t_ = s.t_;
00155             return *this;
00156         }
00157         template<class AE>
00158         BOOST_UBLAS_INLINE
00159         scalar_value &operator = (const scalar_expression<AE> &ae) {
00160             t_ = ae;
00161             return *this;
00162         }
00163 
00164         // Closure comparison
00165         BOOST_UBLAS_INLINE
00166         bool same_closure (const scalar_value &sv) const {
00167             return this == &sv;    // self closing on instances value
00168         }
00169 
00170     private:
00171         value_type t_;
00172     };
00173 
00174 
00182     template<class E>
00183     class vector_expression:
00184         public ublas_expression<E> {
00185     public:
00186         static const unsigned complexity = 0;
00187         typedef E expression_type;
00188         typedef vector_tag type_category;
00189         /* E can be an incomplete type - to define the following we would need more template arguments
00190         typedef typename E::size_type size_type;
00191         */
00192  
00193         BOOST_UBLAS_INLINE
00194         const expression_type &operator () () const {
00195             return *static_cast<const expression_type *> (this);
00196         }
00197         BOOST_UBLAS_INLINE
00198         expression_type &operator () () {
00199             return *static_cast<expression_type *> (this);
00200         }
00201 
00202 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
00203     private:
00204         // projection types
00205         typedef vector_range<E> vector_range_type;
00206         typedef vector_range<const E> const_vector_range_type;
00207         typedef vector_slice<E> vector_slice_type;
00208         typedef vector_slice<const E> const_vector_slice_type;
00209         // vector_indirect_type will depend on the A template parameter 
00210         typedef basic_range<> default_range;    // required to avoid range/slice name confusion
00211         typedef basic_slice<> default_slice;
00212    public:
00213         BOOST_UBLAS_INLINE
00214         const_vector_range_type operator () (const default_range &r) const {
00215             return const_vector_range_type (operator () (), r);
00216         }
00217         BOOST_UBLAS_INLINE
00218         vector_range_type operator () (const default_range &r) {
00219             return vector_range_type (operator () (), r);
00220         }
00221         BOOST_UBLAS_INLINE
00222         const_vector_slice_type operator () (const default_slice &s) const {
00223             return const_vector_slice_type (operator () (), s);
00224         }
00225         BOOST_UBLAS_INLINE
00226         vector_slice_type operator () (const default_slice &s) {
00227             return vector_slice_type (operator () (), s);
00228         }
00229         template<class A>
00230         BOOST_UBLAS_INLINE
00231         const vector_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia) const {
00232             return vector_indirect<const E, indirect_array<A> >  (operator () (), ia);
00233         }
00234         template<class A>
00235         BOOST_UBLAS_INLINE
00236         vector_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia) {
00237             return vector_indirect<E, indirect_array<A> > (operator () (), ia);
00238         }
00239 
00240         BOOST_UBLAS_INLINE
00241         const_vector_range_type project (const default_range &r) const {
00242             return const_vector_range_type (operator () (), r);
00243         }
00244         BOOST_UBLAS_INLINE
00245         vector_range_type project (const default_range &r) {
00246             return vector_range_type (operator () (), r);
00247         }
00248         BOOST_UBLAS_INLINE
00249         const_vector_slice_type project (const default_slice &s) const {
00250             return const_vector_slice_type (operator () (), s);
00251         }
00252         BOOST_UBLAS_INLINE
00253         vector_slice_type project (const default_slice &s) {
00254             return vector_slice_type (operator () (), s);
00255         }
00256         template<class A>
00257         BOOST_UBLAS_INLINE
00258         const vector_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia) const {
00259             return vector_indirect<const E, indirect_array<A> > (operator () (), ia);
00260         }
00261         template<class A>
00262         BOOST_UBLAS_INLINE
00263         vector_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia) {
00264             return vector_indirect<E, indirect_array<A> > (operator () (), ia);
00265         }
00266 #endif
00267     };
00268 
00276     template<class C>
00277     class vector_container:
00278         public vector_expression<C> {
00279     public:
00280         static const unsigned complexity = 0;
00281         typedef C container_type;
00282         typedef vector_tag type_category;
00283  
00284         BOOST_UBLAS_INLINE
00285         const container_type &operator () () const {
00286             return *static_cast<const container_type *> (this);
00287         }
00288         BOOST_UBLAS_INLINE
00289         container_type &operator () () {
00290             return *static_cast<container_type *> (this);
00291         }
00292 
00293 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
00294         using vector_expression<C>::operator ();
00295 #endif
00296     };
00297 
00298 
00306     template<class E>
00307     class matrix_expression:
00308         public ublas_expression<E> {
00309     private:
00310         typedef matrix_expression<E> self_type;
00311     public:
00312         static const unsigned complexity = 0;
00313         typedef E expression_type;
00314         typedef matrix_tag type_category;
00315         /* E can be an incomplete type - to define the following we would need more template arguments
00316         typedef typename E::size_type size_type;
00317         */
00318 
00319         BOOST_UBLAS_INLINE
00320         const expression_type &operator () () const {
00321             return *static_cast<const expression_type *> (this);
00322         }
00323         BOOST_UBLAS_INLINE
00324         expression_type &operator () () {
00325             return *static_cast<expression_type *> (this);
00326         }
00327 
00328 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
00329     private:
00330         // projection types
00331         typedef vector_range<E> vector_range_type;
00332         typedef const vector_range<const E> const_vector_range_type;
00333         typedef vector_slice<E> vector_slice_type;
00334         typedef const vector_slice<const E> const_vector_slice_type;
00335         typedef matrix_row<E> matrix_row_type;
00336         typedef const matrix_row<const E> const_matrix_row_type;
00337         typedef matrix_column<E> matrix_column_type;
00338         typedef const  matrix_column<const E> const_matrix_column_type;
00339         typedef matrix_range<E> matrix_range_type;
00340         typedef const matrix_range<const E> const_matrix_range_type;
00341         typedef matrix_slice<E> matrix_slice_type;
00342         typedef const matrix_slice<const E> const_matrix_slice_type;
00343         // matrix_indirect_type will depend on the A template parameter 
00344         typedef basic_range<> default_range;    // required to avoid range/slice name confusion
00345         typedef basic_slice<> default_slice;
00346 
00347     public:
00348         BOOST_UBLAS_INLINE
00349         const_matrix_row_type operator [] (std::size_t i) const {
00350             return const_matrix_row_type (operator () (), i);
00351         }
00352         BOOST_UBLAS_INLINE
00353         matrix_row_type operator [] (std::size_t i) {
00354             return matrix_row_type (operator () (), i);
00355         }
00356         BOOST_UBLAS_INLINE
00357         const_matrix_row_type row (std::size_t i) const {
00358             return const_matrix_row_type (operator () (), i);
00359         }
00360         BOOST_UBLAS_INLINE
00361         matrix_row_type row (std::size_t i) {
00362             return matrix_row_type (operator () (), i);
00363         }
00364         BOOST_UBLAS_INLINE
00365         const_matrix_column_type column (std::size_t j) const {
00366             return const_matrix_column_type (operator () (), j);
00367         }
00368         BOOST_UBLAS_INLINE
00369         matrix_column_type column (std::size_t j) {
00370             return matrix_column_type (operator () (), j);
00371         }
00372 
00373         BOOST_UBLAS_INLINE
00374         const_matrix_range_type operator () (const default_range &r1, const default_range &r2) const {
00375             return const_matrix_range_type (operator () (), r1, r2);
00376         }
00377         BOOST_UBLAS_INLINE
00378         matrix_range_type operator () (const default_range &r1, const default_range &r2) {
00379             return matrix_range_type (operator () (), r1, r2);
00380         }
00381         BOOST_UBLAS_INLINE
00382         const_matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) const {
00383             return const_matrix_slice_type (operator () (), s1, s2);
00384         }
00385         BOOST_UBLAS_INLINE
00386         matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) {
00387             return matrix_slice_type (operator () (), s1, s2);
00388         }
00389         template<class A>
00390         BOOST_UBLAS_INLINE
00391         const matrix_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const {
00392             return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2);
00393         }
00394         template<class A>
00395         BOOST_UBLAS_INLINE
00396         matrix_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
00397             return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2);
00398         }
00399 
00400         BOOST_UBLAS_INLINE
00401         const_matrix_range_type project (const default_range &r1, const default_range &r2) const {
00402             return const_matrix_range_type (operator () (), r1, r2);
00403         }
00404         BOOST_UBLAS_INLINE
00405         matrix_range_type project (const default_range &r1, const default_range &r2) {
00406             return matrix_range_type (operator () (), r1, r2);
00407         }
00408         BOOST_UBLAS_INLINE
00409         const_matrix_slice_type project (const default_slice &s1, const default_slice &s2) const {
00410             return const_matrix_slice_type (operator () (), s1, s2);
00411         }
00412         BOOST_UBLAS_INLINE
00413         matrix_slice_type project (const default_slice &s1, const default_slice &s2) {
00414             return matrix_slice_type (operator () (), s1, s2);
00415         }
00416         template<class A>
00417         BOOST_UBLAS_INLINE
00418         const matrix_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const {
00419             return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2);
00420         }
00421         template<class A>
00422         BOOST_UBLAS_INLINE
00423         matrix_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
00424             return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2);
00425         }
00426 #endif
00427     };
00428 
00429 #ifdef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
00430     struct iterator1_tag {};
00431     struct iterator2_tag {};
00432 
00433     template<class I>
00434     BOOST_UBLAS_INLINE
00435     typename I::dual_iterator_type begin (const I &it, iterator1_tag) {
00436         return it ().find2 (1, it.index1 (), 0);
00437     }
00438     template<class I>
00439     BOOST_UBLAS_INLINE
00440     typename I::dual_iterator_type end (const I &it, iterator1_tag) {
00441         return it ().find2 (1, it.index1 (), it ().size2 ());
00442     }
00443     template<class I>
00444     BOOST_UBLAS_INLINE
00445     typename I::dual_reverse_iterator_type rbegin (const I &it, iterator1_tag) {
00446         return typename I::dual_reverse_iterator_type (end (it, iterator1_tag ()));
00447     }
00448     template<class I>
00449     BOOST_UBLAS_INLINE
00450     typename I::dual_reverse_iterator_type rend (const I &it, iterator1_tag) {
00451         return typename I::dual_reverse_iterator_type (begin (it, iterator1_tag ()));
00452     }
00453 
00454     template<class I>
00455     BOOST_UBLAS_INLINE
00456     typename I::dual_iterator_type begin (const I &it, iterator2_tag) {
00457         return it ().find1 (1, 0, it.index2 ());
00458     }
00459     template<class I>
00460     BOOST_UBLAS_INLINE
00461     typename I::dual_iterator_type end (const I &it, iterator2_tag) {
00462         return it ().find1 (1, it ().size1 (), it.index2 ());
00463     }
00464     template<class I>
00465     BOOST_UBLAS_INLINE
00466     typename I::dual_reverse_iterator_type rbegin (const I &it, iterator2_tag) {
00467         return typename I::dual_reverse_iterator_type (end (it, iterator2_tag ()));
00468     }
00469     template<class I>
00470     BOOST_UBLAS_INLINE
00471     typename I::dual_reverse_iterator_type rend (const I &it, iterator2_tag) {
00472         return typename I::dual_reverse_iterator_type (begin (it, iterator2_tag ()));
00473     }
00474 #endif
00475 
00483     template<class C>
00484     class matrix_container:
00485         public matrix_expression<C> {
00486     public:
00487         static const unsigned complexity = 0;
00488         typedef C container_type;
00489         typedef matrix_tag type_category;
00490 
00491         BOOST_UBLAS_INLINE
00492         const container_type &operator () () const {
00493             return *static_cast<const container_type *> (this);
00494         }
00495         BOOST_UBLAS_INLINE
00496         container_type &operator () () {
00497             return *static_cast<container_type *> (this);
00498         }
00499 
00500 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
00501         using matrix_expression<C>::operator ();
00502 #endif
00503     };
00504 
00505 }}}
00506 
00507 #endif