462 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			462 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| // Copyright 2002 The Trustees of Indiana University.
 | |
| 
 | |
| // Use, modification and distribution is subject to 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)
 | |
| 
 | |
| //  Boost.MultiArray Library
 | |
| //  Authors: Ronald Garcia
 | |
| //           Jeremy Siek
 | |
| //           Andrew Lumsdaine
 | |
| //  See http://www.boost.org/libs/multi_array for documentation.
 | |
| 
 | |
| #ifndef BOOST_MULTI_ARRAY_VIEW_RG071301_HPP
 | |
| #define BOOST_MULTI_ARRAY_VIEW_RG071301_HPP
 | |
| 
 | |
| //
 | |
| // view.hpp - code for creating "views" of array data.
 | |
| //
 | |
| 
 | |
| #include "boost/multi_array/base.hpp"
 | |
| #include "boost/multi_array/concept_checks.hpp"
 | |
| #include "boost/multi_array/iterator.hpp"
 | |
| #include "boost/multi_array/storage_order.hpp"
 | |
| #include "boost/multi_array/subarray.hpp"
 | |
| #include "boost/multi_array/algorithm.hpp"
 | |
| #include "boost/type_traits/is_integral.hpp"
 | |
| #include "boost/utility/enable_if.hpp"
 | |
| #include "boost/array.hpp"
 | |
| #include "boost/limits.hpp"
 | |
| #include <algorithm>
 | |
| #include <cstddef>
 | |
| #include <functional>
 | |
| #include <numeric>
 | |
| 
 | |
| namespace boost {
 | |
| namespace detail {
 | |
| namespace multi_array {
 | |
| 
 | |
| // TPtr = const T* defaulted in base.hpp
 | |
| template <typename T, std::size_t NumDims, typename TPtr>
 | |
| class const_multi_array_view :
 | |
|     public boost::detail::multi_array::multi_array_impl_base<T,NumDims>
 | |
| {
 | |
|   typedef boost::detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
 | |
| public: 
 | |
|   typedef typename super_type::value_type value_type;
 | |
|   typedef typename super_type::const_reference const_reference;
 | |
|   typedef typename super_type::const_iterator const_iterator;
 | |
|   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
 | |
|   typedef typename super_type::element element;
 | |
|   typedef typename super_type::size_type size_type;
 | |
|   typedef typename super_type::difference_type difference_type;
 | |
|   typedef typename super_type::index index;
 | |
|   typedef typename super_type::extent_range extent_range;
 | |
| 
 | |
|   // template typedefs
 | |
|   template <std::size_t NDims>
 | |
|   struct const_array_view {
 | |
|     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
 | |
|   };
 | |
| 
 | |
|   template <std::size_t NDims>
 | |
|   struct array_view {
 | |
|     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
 | |
|   };
 | |
| 
 | |
|   template <typename OPtr>
 | |
|   const_multi_array_view(const 
 | |
|                          const_multi_array_view<T,NumDims,OPtr>& other) :
 | |
|     base_(other.base_), origin_offset_(other.origin_offset_),
 | |
|     num_elements_(other.num_elements_), extent_list_(other.extent_list_),
 | |
|     stride_list_(other.stride_list_), index_base_list_(other.index_base_list_)
 | |
|   { }
 | |
| 
 | |
| 
 | |
|   template <class BaseList>
 | |
| #ifdef BOOST_NO_SFINAE
 | |
|   void
 | |
| #else
 | |
|   typename
 | |
|   disable_if<typename boost::is_integral<BaseList>::type,void >::type
 | |
| #endif
 | |
|   reindex(const BaseList& values) {
 | |
|     boost::function_requires<
 | |
|       CollectionConcept<BaseList> >();
 | |
|     boost::detail::multi_array::
 | |
|       copy_n(values.begin(),num_dimensions(),index_base_list_.begin());
 | |
|     origin_offset_ =
 | |
|       this->calculate_indexing_offset(stride_list_,index_base_list_);
 | |
|   }
 | |
| 
 | |
|   void reindex(index value) {
 | |
|     index_base_list_.assign(value);
 | |
|     origin_offset_ =
 | |
|       this->calculate_indexing_offset(stride_list_,index_base_list_);
 | |
|   }
 | |
| 
 | |
|   size_type num_dimensions() const { return NumDims; }
 | |
| 
 | |
|   size_type size() const { return extent_list_.front(); }
 | |
|   size_type max_size() const { return num_elements(); }
 | |
|   bool empty() const { return size() == 0; }
 | |
| 
 | |
|   const size_type* shape() const {
 | |
|     return extent_list_.data();
 | |
|   }
 | |
| 
 | |
|   const index* strides() const {
 | |
|     return stride_list_.data();
 | |
|   }
 | |
| 
 | |
|   const T* origin() const { return base_+origin_offset_; }
 | |
| 
 | |
|   size_type num_elements() const { return num_elements_; }
 | |
| 
 | |
|   const index* index_bases() const {
 | |
|     return index_base_list_.data();
 | |
|   }
 | |
| 
 | |
|   template <typename IndexList>
 | |
|   const element& operator()(IndexList indices) const {
 | |
|     boost::function_requires<
 | |
|       CollectionConcept<IndexList> >();
 | |
|     return super_type::access_element(boost::type<const element&>(),
 | |
|                                       indices,origin(),
 | |
|                                       shape(),strides(),index_bases());
 | |
|   }
 | |
| 
 | |
|   // Only allow const element access
 | |
|   const_reference operator[](index idx) const {
 | |
|     return super_type::access(boost::type<const_reference>(),
 | |
|                               idx,origin(),
 | |
|                               shape(),strides(),
 | |
|                               index_bases());
 | |
|   }
 | |
| 
 | |
|   // see generate_array_view in base.hpp
 | |
|   template <int NDims>
 | |
|   typename const_array_view<NDims>::type 
 | |
|   operator[](const boost::detail::multi_array::
 | |
|              index_gen<NumDims,NDims>& indices)
 | |
|     const {
 | |
|     typedef typename const_array_view<NDims>::type return_type;
 | |
|     return
 | |
|       super_type::generate_array_view(boost::type<return_type>(),
 | |
|                                       indices,
 | |
|                                       shape(),
 | |
|                                       strides(),
 | |
|                                       index_bases(),
 | |
|                                       origin());
 | |
|   }
 | |
|   const_iterator begin() const {
 | |
|     return const_iterator(*index_bases(),origin(),
 | |
|                           shape(),strides(),index_bases());
 | |
|   }
 | |
| 
 | |
|   const_iterator end() const {
 | |
|     return const_iterator(*index_bases()+(index)*shape(),origin(),
 | |
|                           shape(),strides(),index_bases());
 | |
|   }
 | |
|   
 | |
|   const_reverse_iterator rbegin() const {
 | |
|     return const_reverse_iterator(end());
 | |
|   }
 | |
| 
 | |
|   const_reverse_iterator rend() const {
 | |
|     return const_reverse_iterator(begin());
 | |
|   }
 | |
| 
 | |
| 
 | |
|   template <typename OPtr>
 | |
|   bool operator==(const
 | |
|                   const_multi_array_view<T,NumDims,OPtr>& rhs)
 | |
|     const {
 | |
|     if(std::equal(extent_list_.begin(),
 | |
|                   extent_list_.end(),
 | |
|                   rhs.extent_list_.begin()))
 | |
|       return std::equal(begin(),end(),rhs.begin());
 | |
|     else return false;
 | |
|   }
 | |
| 
 | |
|   template <typename OPtr>
 | |
|   bool operator<(const
 | |
|                  const_multi_array_view<T,NumDims,OPtr>& rhs)
 | |
|     const {
 | |
|     return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
 | |
|   }
 | |
| 
 | |
|   template <typename OPtr>
 | |
|   bool operator!=(const
 | |
|                   const_multi_array_view<T,NumDims,OPtr>& rhs)
 | |
|     const {
 | |
|     return !(*this == rhs);
 | |
|   }
 | |
| 
 | |
|   template <typename OPtr>
 | |
|   bool operator>(const
 | |
|                  const_multi_array_view<T,NumDims,OPtr>& rhs)
 | |
|     const {
 | |
|     return rhs < *this;
 | |
|   }
 | |
| 
 | |
|   template <typename OPtr>
 | |
|   bool operator<=(const
 | |
|                  const_multi_array_view<T,NumDims,OPtr>& rhs)
 | |
|     const {
 | |
|     return !(*this > rhs);
 | |
|   }
 | |
| 
 | |
|   template <typename OPtr>
 | |
|   bool operator>=(const
 | |
|                  const_multi_array_view<T,NumDims,OPtr>& rhs)
 | |
|     const {
 | |
|     return !(*this < rhs);
 | |
|   }
 | |
| 
 | |
| 
 | |
| #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
 | |
| protected:
 | |
|   template <typename,std::size_t> friend class multi_array_impl_base;
 | |
|   template <typename,std::size_t,typename> friend class const_multi_array_view;
 | |
| #else
 | |
| public: // should be protected
 | |
| #endif
 | |
| 
 | |
|   // This constructor is used by multi_array_impl_base::generate_array_view
 | |
|   // to create strides  
 | |
|   template <typename ExtentList, typename Index>
 | |
|   explicit const_multi_array_view(TPtr base,
 | |
|                            const ExtentList& extents,
 | |
|                            const boost::array<Index,NumDims>& strides): 
 | |
|     base_(base), origin_offset_(0) {
 | |
| 
 | |
|     index_base_list_.assign(0);
 | |
| 
 | |
|     // Get the extents and strides
 | |
|     boost::detail::multi_array::
 | |
|       copy_n(extents.begin(),NumDims,extent_list_.begin());
 | |
|     boost::detail::multi_array::
 | |
|       copy_n(strides.begin(),NumDims,stride_list_.begin());
 | |
| 
 | |
|     // Calculate the array size
 | |
|     num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
 | |
|                                     size_type(1),std::multiplies<size_type>());
 | |
|   }
 | |
| 
 | |
|   typedef boost::array<size_type,NumDims> size_list;
 | |
|   typedef boost::array<index,NumDims> index_list;
 | |
| 
 | |
|   TPtr base_;
 | |
|   index origin_offset_;
 | |
|   size_type num_elements_;
 | |
|   size_list extent_list_;
 | |
|   index_list stride_list_;
 | |
|   index_list index_base_list_;
 | |
| 
 | |
| private:
 | |
|   // const_multi_array_view cannot be assigned to (no deep copies!)
 | |
|   const_multi_array_view& operator=(const const_multi_array_view& other);
 | |
| };
 | |
| 
 | |
| 
 | |
| template <typename T, std::size_t NumDims>
 | |
| class multi_array_view :
 | |
|   public const_multi_array_view<T,NumDims,T*>
 | |
| {
 | |
|   typedef const_multi_array_view<T,NumDims,T*> super_type;
 | |
| public: 
 | |
|   typedef typename super_type::value_type value_type;
 | |
|   typedef typename super_type::reference reference;
 | |
|   typedef typename super_type::iterator iterator;
 | |
|   typedef typename super_type::reverse_iterator reverse_iterator;
 | |
|   typedef typename super_type::const_reference const_reference;
 | |
|   typedef typename super_type::const_iterator const_iterator;
 | |
|   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
 | |
|   typedef typename super_type::element element;
 | |
|   typedef typename super_type::size_type size_type;
 | |
|   typedef typename super_type::difference_type difference_type;
 | |
|   typedef typename super_type::index index;
 | |
|   typedef typename super_type::extent_range extent_range;
 | |
| 
 | |
|   // template typedefs
 | |
|   template <std::size_t NDims>
 | |
|   struct const_array_view {
 | |
|     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
 | |
|   };
 | |
| 
 | |
|   template <std::size_t NDims>
 | |
|   struct array_view {
 | |
|     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
 | |
|   };
 | |
| 
 | |
|   // Assignment from other ConstMultiArray types.
 | |
|   template <typename ConstMultiArray>
 | |
|   multi_array_view& operator=(const ConstMultiArray& other) {
 | |
|     function_requires< 
 | |
|       boost::multi_array_concepts::
 | |
|       ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
 | |
| 
 | |
|     // make sure the dimensions agree
 | |
|     BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
 | |
|     BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(),
 | |
|                             this->shape()));
 | |
|     // iterator-based copy
 | |
|     std::copy(other.begin(),other.end(),begin());
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   multi_array_view& operator=(const multi_array_view& other) {
 | |
|     if (&other != this) {
 | |
|       // make sure the dimensions agree
 | |
|       BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
 | |
|       BOOST_ASSERT(std::equal(other.shape(),
 | |
|                               other.shape()+this->num_dimensions(),
 | |
|                               this->shape()));
 | |
|       // iterator-based copy
 | |
|       std::copy(other.begin(),other.end(),begin());
 | |
|     }
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   element* origin() { return this->base_+this->origin_offset_; }
 | |
| 
 | |
|   template <class IndexList>
 | |
|   element& operator()(const IndexList& indices) {
 | |
|     boost::function_requires<
 | |
|       CollectionConcept<IndexList> >();
 | |
|     return super_type::access_element(boost::type<element&>(),
 | |
|                                       indices,origin(),
 | |
|                                       this->shape(),this->strides(),
 | |
|                                       this->index_bases());
 | |
|   }
 | |
| 
 | |
| 
 | |
|   reference operator[](index idx) {
 | |
|     return super_type::access(boost::type<reference>(),
 | |
|                               idx,origin(),
 | |
|                               this->shape(),this->strides(),
 | |
|                               this->index_bases());
 | |
|   }
 | |
| 
 | |
| 
 | |
|   // see generate_array_view in base.hpp
 | |
|   template <int NDims>
 | |
|   typename array_view<NDims>::type 
 | |
|   operator[](const boost::detail::multi_array::
 | |
|              index_gen<NumDims,NDims>& indices) {
 | |
|     typedef typename array_view<NDims>::type return_type;
 | |
|     return
 | |
|       super_type::generate_array_view(boost::type<return_type>(),
 | |
|                                       indices,
 | |
|                                       this->shape(),
 | |
|                                       this->strides(),
 | |
|                                       this->index_bases(),
 | |
|                                       origin());
 | |
|   }
 | |
|   
 | |
|   
 | |
|   iterator begin() {
 | |
|     return iterator(*this->index_bases(),origin(),
 | |
|                     this->shape(),this->strides(),
 | |
|                     this->index_bases());
 | |
|   }
 | |
| 
 | |
|   iterator end() {
 | |
|     return iterator(*this->index_bases()+(index)*this->shape(),origin(),
 | |
|                     this->shape(),this->strides(),
 | |
|                     this->index_bases());
 | |
|   }
 | |
| 
 | |
|   reverse_iterator rbegin() {
 | |
|     return reverse_iterator(end());
 | |
|   }
 | |
| 
 | |
|   reverse_iterator rend() {
 | |
|     return reverse_iterator(begin());
 | |
|   }
 | |
| 
 | |
|   // Using declarations don't seem to work for g++
 | |
|   // These are the proxies to work around this.
 | |
| 
 | |
|   const element* origin() const { return super_type::origin(); }
 | |
| 
 | |
|   template <class IndexList>
 | |
|   const element& operator()(const IndexList& indices) const {
 | |
|     boost::function_requires<
 | |
|       CollectionConcept<IndexList> >();
 | |
|     return super_type::operator()(indices);
 | |
|   }
 | |
| 
 | |
|   const_reference operator[](index idx) const {
 | |
|     return super_type::operator[](idx);
 | |
|   }
 | |
| 
 | |
|   // see generate_array_view in base.hpp
 | |
|   template <int NDims>
 | |
|   typename const_array_view<NDims>::type 
 | |
|   operator[](const boost::detail::multi_array::
 | |
|              index_gen<NumDims,NDims>& indices)
 | |
|     const {
 | |
|     return super_type::operator[](indices);
 | |
|   }
 | |
|   
 | |
|   const_iterator begin() const {
 | |
|     return super_type::begin();
 | |
|   }
 | |
| 
 | |
|   const_iterator end() const {
 | |
|     return super_type::end();
 | |
|   }
 | |
| 
 | |
|   const_reverse_iterator rbegin() const {
 | |
|     return super_type::rbegin();
 | |
|   }
 | |
| 
 | |
|   const_reverse_iterator rend() const {
 | |
|     return super_type::rend();
 | |
|   }
 | |
| 
 | |
| #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
 | |
| private:
 | |
|   template <typename,std::size_t> friend class multi_array_impl_base;
 | |
| #else
 | |
| public: // should be private
 | |
| #endif
 | |
| 
 | |
|   // constructor used by multi_array_impl_base::generate_array_view to
 | |
|   // generate array views
 | |
|   template <typename ExtentList, typename Index>
 | |
|   explicit multi_array_view(T* base,
 | |
|                             const ExtentList& extents,
 | |
|                             const boost::array<Index,NumDims>& strides) :
 | |
|     super_type(base,extents,strides) { }
 | |
| 
 | |
| };
 | |
| 
 | |
| } // namespace multi_array
 | |
| } // namespace detail
 | |
| 
 | |
| //
 | |
| // traits classes to get array_view types
 | |
| //
 | |
| template <typename Array, int N>
 | |
| class array_view_gen {
 | |
|   typedef typename Array::element element;
 | |
| public:
 | |
|   typedef boost::detail::multi_array::multi_array_view<element,N> type;
 | |
| };
 | |
| 
 | |
| template <typename Array, int N>
 | |
| class const_array_view_gen {
 | |
|   typedef typename Array::element element;
 | |
| public:
 | |
|   typedef boost::detail::multi_array::const_multi_array_view<element,N> type;  
 | |
| };
 | |
| 
 | |
| } // namespace boost
 | |
| 
 | |
| #endif // BOOST_MULTI_ARRAY_VIEW_RG071301_HPP
 | |
| 
 | 
