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