- Main Page
- Related Pages
- Classes
- Files

- File List

# expression_types.hpp

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