507 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			507 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| //  Copyright (c) 2000-2013
 | |
| //  Joerg Walter, Mathias Koch. David Bellot
 | |
| //
 | |
| //  Distributed under the Boost Software License, Version 1.0. (See
 | |
| //  accompanying file LICENSE_1_0.txt or copy at
 | |
| //  http://www.boost.org/LICENSE_1_0.txt)
 | |
| //
 | |
| //  The authors gratefully acknowledge the support of
 | |
| //  GeNeSys mbH & Co. KG in producing this work.
 | |
| //
 | |
| #ifndef _BOOST_UBLAS_EXPRESSION_TYPE_
 | |
| #define _BOOST_UBLAS_EXPRESSION_TYPE_
 | |
| 
 | |
| #include <boost/numeric/ublas/exception.hpp>
 | |
| #include <boost/numeric/ublas/traits.hpp>
 | |
| #include <boost/numeric/ublas/functional.hpp>
 | |
| 
 | |
| 
 | |
| // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
 | |
| // Iterators based on ideas of Jeremy Siek
 | |
| 
 | |
| namespace boost { namespace numeric { namespace ublas {
 | |
| 
 | |
|     /** \brief Base class for uBLAS statically derived expressions using the the Barton Nackman trick
 | |
|      *
 | |
|      * This is a NonAssignable class
 | |
|      * Directly implement nonassignable - simplifes debugging call trace!
 | |
|      * 
 | |
|      * \tparam E an expression type
 | |
|      */
 | |
|     template<class E>
 | |
|     class ublas_expression {
 | |
|     public:
 | |
|         typedef E expression_type;
 | |
|         /* E can be an incomplete type - to define the following we would need more template arguments
 | |
|         typedef typename E::type_category type_category;
 | |
|         typedef typename E::value_type value_type;
 | |
|         */
 | |
|         
 | |
|     protected:
 | |
|         ublas_expression () {}
 | |
|         ~ublas_expression () {}
 | |
|     private:
 | |
|         const ublas_expression& operator= (const ublas_expression &);
 | |
|     };
 | |
| 
 | |
| 
 | |
|     /** \brief Base class for Scalar Expression models
 | |
|      *
 | |
|      * It does not model the Scalar Expression concept but all derived types should.
 | |
|      * The class defines a common base type and some common interface for all statically 
 | |
|      * derived Scalar Expression classes.
 | |
|      *
 | |
|      * We implement the casts to the statically derived type.
 | |
|      *
 | |
|      * \tparam E an expression type
 | |
|      */
 | |
|     template<class E>
 | |
|     class scalar_expression:
 | |
|         public ublas_expression<E> {
 | |
|     public:
 | |
|         typedef E expression_type;
 | |
|         typedef scalar_tag type_category;
 | |
| 
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const expression_type &operator () () const {
 | |
|             return *static_cast<const expression_type *> (this);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         expression_type &operator () () {
 | |
|             return *static_cast<expression_type *> (this);
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     template<class T>
 | |
|     class scalar_reference:
 | |
|         public scalar_expression<scalar_reference<T> > {
 | |
| 
 | |
|         typedef scalar_reference<T> self_type;
 | |
|     public:
 | |
|         typedef T value_type;
 | |
|         typedef const value_type &const_reference;
 | |
|         typedef typename boost::mpl::if_<boost::is_const<T>,
 | |
|                                           const_reference,
 | |
|                                           value_type &>::type reference;
 | |
|         typedef const self_type const_closure_type;
 | |
|         typedef const_closure_type closure_type;
 | |
| 
 | |
|         // Construction and destruction
 | |
|         BOOST_UBLAS_INLINE
 | |
|         explicit scalar_reference (reference t):
 | |
|             t_ (t) {}
 | |
| 
 | |
|         // Conversion
 | |
|         BOOST_UBLAS_INLINE
 | |
|         operator value_type () const {
 | |
|             return t_;
 | |
|         }
 | |
| 
 | |
|         // Assignment
 | |
|         BOOST_UBLAS_INLINE
 | |
|         scalar_reference &operator = (const scalar_reference &s) {
 | |
|             t_ = s.t_;
 | |
|             return *this;
 | |
|         }
 | |
|         template<class AE>
 | |
|         BOOST_UBLAS_INLINE
 | |
|         scalar_reference &operator = (const scalar_expression<AE> &ae) {
 | |
|             t_ = ae;
 | |
|             return *this;
 | |
|         }
 | |
| 
 | |
|         // Closure comparison
 | |
|         BOOST_UBLAS_INLINE
 | |
|         bool same_closure (const scalar_reference &sr) const {
 | |
|             return &t_ == &sr.t_;
 | |
|         }
 | |
| 
 | |
|     private:
 | |
|         reference t_;
 | |
|     };
 | |
| 
 | |
|     template<class T>
 | |
|     class scalar_value:
 | |
|         public scalar_expression<scalar_value<T> > {
 | |
| 
 | |
|         typedef scalar_value<T> self_type;
 | |
|     public:
 | |
|         typedef T value_type;
 | |
|         typedef const value_type &const_reference;
 | |
|         typedef typename boost::mpl::if_<boost::is_const<T>,
 | |
|                                           const_reference,
 | |
|                                           value_type &>::type reference;
 | |
|         typedef const scalar_reference<const self_type> const_closure_type;
 | |
|         typedef scalar_reference<self_type> closure_type;
 | |
| 
 | |
|         // Construction and destruction
 | |
|         BOOST_UBLAS_INLINE
 | |
|         scalar_value ():
 | |
|             t_ () {}
 | |
|         BOOST_UBLAS_INLINE
 | |
|         scalar_value (const value_type &t):
 | |
|             t_ (t) {}
 | |
| 
 | |
|         BOOST_UBLAS_INLINE
 | |
|         operator value_type () const {
 | |
|             return t_;
 | |
|         }
 | |
| 
 | |
|         // Assignment
 | |
|         BOOST_UBLAS_INLINE
 | |
|         scalar_value &operator = (const scalar_value &s) {
 | |
|             t_ = s.t_;
 | |
|             return *this;
 | |
|         }
 | |
|         template<class AE>
 | |
|         BOOST_UBLAS_INLINE
 | |
|         scalar_value &operator = (const scalar_expression<AE> &ae) {
 | |
|             t_ = ae;
 | |
|             return *this;
 | |
|         }
 | |
| 
 | |
|         // Closure comparison
 | |
|         BOOST_UBLAS_INLINE
 | |
|         bool same_closure (const scalar_value &sv) const {
 | |
|             return this == &sv;    // self closing on instances value
 | |
|         }
 | |
| 
 | |
|     private:
 | |
|         value_type t_;
 | |
|     };
 | |
| 
 | |
| 
 | |
|     /** \brief Base class for Vector Expression models
 | |
|      *
 | |
|      * it does not model the Vector Expression concept but all derived types should.
 | |
|      * The class defines a common base type and some common interface for all
 | |
|      * statically derived Vector Expression classes.
 | |
|      * We implement the casts to the statically derived type.
 | |
|      */
 | |
|     template<class E>
 | |
|     class vector_expression:
 | |
|         public ublas_expression<E> {
 | |
|     public:
 | |
|         static const unsigned complexity = 0;
 | |
|         typedef E expression_type;
 | |
|         typedef vector_tag type_category;
 | |
|         /* E can be an incomplete type - to define the following we would need more template arguments
 | |
|         typedef typename E::size_type size_type;
 | |
|         */
 | |
|  
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const expression_type &operator () () const {
 | |
|             return *static_cast<const expression_type *> (this);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         expression_type &operator () () {
 | |
|             return *static_cast<expression_type *> (this);
 | |
|         }
 | |
| 
 | |
| #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
 | |
|     private:
 | |
|         // projection types
 | |
|         typedef vector_range<E> vector_range_type;
 | |
|         typedef vector_range<const E> const_vector_range_type;
 | |
|         typedef vector_slice<E> vector_slice_type;
 | |
|         typedef vector_slice<const E> const_vector_slice_type;
 | |
|         // vector_indirect_type will depend on the A template parameter 
 | |
|         typedef basic_range<> default_range;    // required to avoid range/slice name confusion
 | |
|         typedef basic_slice<> default_slice;
 | |
|    public:
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const_vector_range_type operator () (const default_range &r) const {
 | |
|             return const_vector_range_type (operator () (), r);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         vector_range_type operator () (const default_range &r) {
 | |
|             return vector_range_type (operator () (), r);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const_vector_slice_type operator () (const default_slice &s) const {
 | |
|             return const_vector_slice_type (operator () (), s);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         vector_slice_type operator () (const default_slice &s) {
 | |
|             return vector_slice_type (operator () (), s);
 | |
|         }
 | |
|         template<class A>
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const vector_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia) const {
 | |
|             return vector_indirect<const E, indirect_array<A> >  (operator () (), ia);
 | |
|         }
 | |
|         template<class A>
 | |
|         BOOST_UBLAS_INLINE
 | |
|         vector_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia) {
 | |
|             return vector_indirect<E, indirect_array<A> > (operator () (), ia);
 | |
|         }
 | |
| 
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const_vector_range_type project (const default_range &r) const {
 | |
|             return const_vector_range_type (operator () (), r);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         vector_range_type project (const default_range &r) {
 | |
|             return vector_range_type (operator () (), r);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const_vector_slice_type project (const default_slice &s) const {
 | |
|             return const_vector_slice_type (operator () (), s);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         vector_slice_type project (const default_slice &s) {
 | |
|             return vector_slice_type (operator () (), s);
 | |
|         }
 | |
|         template<class A>
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const vector_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia) const {
 | |
|             return vector_indirect<const E, indirect_array<A> > (operator () (), ia);
 | |
|         }
 | |
|         template<class A>
 | |
|         BOOST_UBLAS_INLINE
 | |
|         vector_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia) {
 | |
|             return vector_indirect<E, indirect_array<A> > (operator () (), ia);
 | |
|         }
 | |
| #endif
 | |
|     };
 | |
| 
 | |
|     /** \brief Base class for Vector container models
 | |
|      *
 | |
|      * it does not model the Vector concept but all derived types should.
 | |
|      * The class defines a common base type and some common interface for all
 | |
|      * statically derived Vector classes
 | |
|      * We implement the casts to the statically derived type.
 | |
|      */
 | |
|     template<class C>
 | |
|     class vector_container:
 | |
|         public vector_expression<C> {
 | |
|     public:
 | |
|         static const unsigned complexity = 0;
 | |
|         typedef C container_type;
 | |
|         typedef vector_tag type_category;
 | |
|  
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const container_type &operator () () const {
 | |
|             return *static_cast<const container_type *> (this);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         container_type &operator () () {
 | |
|             return *static_cast<container_type *> (this);
 | |
|         }
 | |
| 
 | |
| #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
 | |
|         using vector_expression<C>::operator ();
 | |
| #endif
 | |
|     };
 | |
| 
 | |
| 
 | |
|     /** \brief Base class for Matrix Expression models
 | |
|      *
 | |
|      * it does not model the Matrix Expression concept but all derived types should.
 | |
|      * The class defines a common base type and some common interface for all
 | |
|      * statically derived Matrix Expression classes
 | |
|      * We implement the casts to the statically derived type.
 | |
|      */
 | |
|     template<class E>
 | |
|     class matrix_expression:
 | |
|         public ublas_expression<E> {
 | |
|     private:
 | |
|         typedef matrix_expression<E> self_type;
 | |
|     public:
 | |
|         static const unsigned complexity = 0;
 | |
|         typedef E expression_type;
 | |
|         typedef matrix_tag type_category;
 | |
|         /* E can be an incomplete type - to define the following we would need more template arguments
 | |
|         typedef typename E::size_type size_type;
 | |
|         */
 | |
| 
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const expression_type &operator () () const {
 | |
|             return *static_cast<const expression_type *> (this);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         expression_type &operator () () {
 | |
|             return *static_cast<expression_type *> (this);
 | |
|         }
 | |
| 
 | |
| #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
 | |
|     private:
 | |
|         // projection types
 | |
|         typedef vector_range<E> vector_range_type;
 | |
|         typedef const vector_range<const E> const_vector_range_type;
 | |
|         typedef vector_slice<E> vector_slice_type;
 | |
|         typedef const vector_slice<const E> const_vector_slice_type;
 | |
|         typedef matrix_row<E> matrix_row_type;
 | |
|         typedef const matrix_row<const E> const_matrix_row_type;
 | |
|         typedef matrix_column<E> matrix_column_type;
 | |
|         typedef const  matrix_column<const E> const_matrix_column_type;
 | |
|         typedef matrix_range<E> matrix_range_type;
 | |
|         typedef const matrix_range<const E> const_matrix_range_type;
 | |
|         typedef matrix_slice<E> matrix_slice_type;
 | |
|         typedef const matrix_slice<const E> const_matrix_slice_type;
 | |
|         // matrix_indirect_type will depend on the A template parameter 
 | |
|         typedef basic_range<> default_range;    // required to avoid range/slice name confusion
 | |
|         typedef basic_slice<> default_slice;
 | |
| 
 | |
|     public:
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const_matrix_row_type operator [] (std::size_t i) const {
 | |
|             return const_matrix_row_type (operator () (), i);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         matrix_row_type operator [] (std::size_t i) {
 | |
|             return matrix_row_type (operator () (), i);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const_matrix_row_type row (std::size_t i) const {
 | |
|             return const_matrix_row_type (operator () (), i);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         matrix_row_type row (std::size_t i) {
 | |
|             return matrix_row_type (operator () (), i);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const_matrix_column_type column (std::size_t j) const {
 | |
|             return const_matrix_column_type (operator () (), j);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         matrix_column_type column (std::size_t j) {
 | |
|             return matrix_column_type (operator () (), j);
 | |
|         }
 | |
| 
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const_matrix_range_type operator () (const default_range &r1, const default_range &r2) const {
 | |
|             return const_matrix_range_type (operator () (), r1, r2);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         matrix_range_type operator () (const default_range &r1, const default_range &r2) {
 | |
|             return matrix_range_type (operator () (), r1, r2);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const_matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) const {
 | |
|             return const_matrix_slice_type (operator () (), s1, s2);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         matrix_slice_type operator () (const default_slice &s1, const default_slice &s2) {
 | |
|             return matrix_slice_type (operator () (), s1, s2);
 | |
|         }
 | |
|         template<class A>
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const matrix_indirect<const E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const {
 | |
|             return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2);
 | |
|         }
 | |
|         template<class A>
 | |
|         BOOST_UBLAS_INLINE
 | |
|         matrix_indirect<E, indirect_array<A> > operator () (const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
 | |
|             return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2);
 | |
|         }
 | |
| 
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const_matrix_range_type project (const default_range &r1, const default_range &r2) const {
 | |
|             return const_matrix_range_type (operator () (), r1, r2);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         matrix_range_type project (const default_range &r1, const default_range &r2) {
 | |
|             return matrix_range_type (operator () (), r1, r2);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const_matrix_slice_type project (const default_slice &s1, const default_slice &s2) const {
 | |
|             return const_matrix_slice_type (operator () (), s1, s2);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         matrix_slice_type project (const default_slice &s1, const default_slice &s2) {
 | |
|             return matrix_slice_type (operator () (), s1, s2);
 | |
|         }
 | |
|         template<class A>
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const matrix_indirect<const E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) const {
 | |
|             return matrix_indirect<const E, indirect_array<A> > (operator () (), ia1, ia2);
 | |
|         }
 | |
|         template<class A>
 | |
|         BOOST_UBLAS_INLINE
 | |
|         matrix_indirect<E, indirect_array<A> > project (const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
 | |
|             return matrix_indirect<E, indirect_array<A> > (operator () (), ia1, ia2);
 | |
|         }
 | |
| #endif
 | |
|     };
 | |
| 
 | |
| #ifdef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
 | |
|     struct iterator1_tag {};
 | |
|     struct iterator2_tag {};
 | |
| 
 | |
|     template<class I>
 | |
|     BOOST_UBLAS_INLINE
 | |
|     typename I::dual_iterator_type begin (const I &it, iterator1_tag) {
 | |
|         return it ().find2 (1, it.index1 (), 0);
 | |
|     }
 | |
|     template<class I>
 | |
|     BOOST_UBLAS_INLINE
 | |
|     typename I::dual_iterator_type end (const I &it, iterator1_tag) {
 | |
|         return it ().find2 (1, it.index1 (), it ().size2 ());
 | |
|     }
 | |
|     template<class I>
 | |
|     BOOST_UBLAS_INLINE
 | |
|     typename I::dual_reverse_iterator_type rbegin (const I &it, iterator1_tag) {
 | |
|         return typename I::dual_reverse_iterator_type (end (it, iterator1_tag ()));
 | |
|     }
 | |
|     template<class I>
 | |
|     BOOST_UBLAS_INLINE
 | |
|     typename I::dual_reverse_iterator_type rend (const I &it, iterator1_tag) {
 | |
|         return typename I::dual_reverse_iterator_type (begin (it, iterator1_tag ()));
 | |
|     }
 | |
| 
 | |
|     template<class I>
 | |
|     BOOST_UBLAS_INLINE
 | |
|     typename I::dual_iterator_type begin (const I &it, iterator2_tag) {
 | |
|         return it ().find1 (1, 0, it.index2 ());
 | |
|     }
 | |
|     template<class I>
 | |
|     BOOST_UBLAS_INLINE
 | |
|     typename I::dual_iterator_type end (const I &it, iterator2_tag) {
 | |
|         return it ().find1 (1, it ().size1 (), it.index2 ());
 | |
|     }
 | |
|     template<class I>
 | |
|     BOOST_UBLAS_INLINE
 | |
|     typename I::dual_reverse_iterator_type rbegin (const I &it, iterator2_tag) {
 | |
|         return typename I::dual_reverse_iterator_type (end (it, iterator2_tag ()));
 | |
|     }
 | |
|     template<class I>
 | |
|     BOOST_UBLAS_INLINE
 | |
|     typename I::dual_reverse_iterator_type rend (const I &it, iterator2_tag) {
 | |
|         return typename I::dual_reverse_iterator_type (begin (it, iterator2_tag ()));
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     /** \brief Base class for Matrix container models
 | |
|      *
 | |
|      * it does not model the Matrix concept but all derived types should.
 | |
|      * The class defines a common base type and some common interface for all
 | |
|      * statically derived Matrix classes
 | |
|      * We implement the casts to the statically derived type.
 | |
|      */
 | |
|     template<class C>
 | |
|     class matrix_container:
 | |
|         public matrix_expression<C> {
 | |
|     public:
 | |
|         static const unsigned complexity = 0;
 | |
|         typedef C container_type;
 | |
|         typedef matrix_tag type_category;
 | |
| 
 | |
|         BOOST_UBLAS_INLINE
 | |
|         const container_type &operator () () const {
 | |
|             return *static_cast<const container_type *> (this);
 | |
|         }
 | |
|         BOOST_UBLAS_INLINE
 | |
|         container_type &operator () () {
 | |
|             return *static_cast<container_type *> (this);
 | |
|         }
 | |
| 
 | |
| #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
 | |
|         using matrix_expression<C>::operator ();
 | |
| #endif
 | |
|     };
 | |
| 
 | |
| }}}
 | |
| 
 | |
| #endif
 | 
