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 SUBARRAY_RG071801_HPP sl@0: #define SUBARRAY_RG071801_HPP sl@0: sl@0: // sl@0: // subarray.hpp - used to implement standard operator[] on sl@0: // multi_arrays 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/limits.hpp" sl@0: #include "boost/type.hpp" 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: // sl@0: // const_sub_array sl@0: // multi_array's proxy class to allow multiple overloads of sl@0: // operator[] in order to provide a clean multi-dimensional array sl@0: // interface. sl@0: template sl@0: class const_sub_array : 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: // Allow default copy constructor as well. sl@0: sl@0: template sl@0: const_sub_array (const const_sub_array& rhs) : sl@0: base_(rhs.base_), extents_(rhs.extents_), strides_(rhs.strides_), sl@0: index_base_(rhs.index_base_) { sl@0: } sl@0: sl@0: // const_sub_array always returns const types, regardless of its own sl@0: // constness. sl@0: const_reference operator[](index idx) const { sl@0: return super_type::access(boost::type(), sl@0: idx,base_,shape(),strides(),index_bases()); sl@0: } 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::access_element(boost::type(), sl@0: indices,origin(), sl@0: shape(),strides(),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: base_); sl@0: } sl@0: sl@0: template sl@0: bool operator<(const const_sub_array& rhs) 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 const_sub_array& rhs) const { sl@0: if(std::equal(shape(),shape()+num_dimensions(),rhs.shape())) 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 const_sub_array& rhs) const { sl@0: return !(*this == rhs); sl@0: } sl@0: sl@0: template sl@0: bool operator>(const const_sub_array& rhs) const { sl@0: return rhs < *this; sl@0: } sl@0: sl@0: template sl@0: bool operator<=(const const_sub_array& rhs) const { sl@0: return !(*this > rhs); sl@0: } sl@0: sl@0: template sl@0: bool operator>=(const const_sub_array& rhs) const { sl@0: return !(*this < rhs); sl@0: } 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: TPtr origin() const { return base_; } sl@0: size_type size() const { return extents_[0]; } sl@0: size_type max_size() const { return num_elements(); } sl@0: bool empty() const { return size() == 0; } sl@0: size_type num_dimensions() const { return NumDims; } sl@0: const size_type* shape() const { return extents_; } sl@0: const index* strides() const { return strides_; } sl@0: const index* index_bases() const { return index_base_; } sl@0: sl@0: size_type num_elements() const { sl@0: return std::accumulate(shape(),shape() + num_dimensions(), sl@0: size_type(1), std::multiplies()); sl@0: } sl@0: sl@0: sl@0: #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS sl@0: protected: sl@0: template friend class value_accessor_n; sl@0: template friend class const_sub_array; sl@0: #else sl@0: public: // Should be protected sl@0: #endif sl@0: sl@0: const_sub_array (TPtr base, sl@0: const size_type* extents, sl@0: const index* strides, sl@0: const index* index_base) : sl@0: base_(base), extents_(extents), strides_(strides), sl@0: index_base_(index_base) { sl@0: } sl@0: sl@0: TPtr base_; sl@0: const size_type* extents_; sl@0: const index* strides_; sl@0: const index* index_base_; sl@0: private: sl@0: // const_sub_array cannot be assigned to (no deep copies!) sl@0: const_sub_array& operator=(const const_sub_array&); sl@0: }; sl@0: sl@0: sl@0: // sl@0: // sub_array sl@0: // multi_array's proxy class to allow multiple overloads of sl@0: // operator[] in order to provide a clean multi-dimensional array sl@0: // interface. sl@0: template sl@0: class sub_array : public const_sub_array sl@0: { sl@0: typedef const_sub_array super_type; sl@0: public: sl@0: typedef typename super_type::element element; sl@0: typedef typename super_type::reference reference; sl@0: typedef typename super_type::index index; sl@0: typedef typename super_type::size_type size_type; 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: 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: sub_array& operator=(const ConstMultiArray& other) { sl@0: function_requires< boost::detail::multi_array::ConstMultiArrayConcept< sl@0: ConstMultiArray, NumDims> >(); 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: sub_array& operator=(const sub_array& 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: T* origin() { return this->base_; } sl@0: const T* origin() const { return this->base_; } sl@0: sl@0: reference operator[](index idx) { sl@0: return super_type::access(boost::type(), sl@0: idx,this->base_,this->shape(),this->strides(), sl@0: this->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 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: 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: iterator begin() { sl@0: return iterator(*this->index_bases(),origin(), sl@0: this->shape(),this->strides(),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(),this->index_bases()); sl@0: } sl@0: sl@0: // RG - rbegin() and rend() written naively to thwart MSVC ICE. sl@0: reverse_iterator rbegin() { sl@0: reverse_iterator ri(end()); sl@0: return ri; sl@0: } sl@0: sl@0: reverse_iterator rend() { sl@0: reverse_iterator ri(begin()); sl@0: return ri; sl@0: } sl@0: sl@0: // sl@0: // proxies sl@0: // 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 value_accessor_n; sl@0: #else sl@0: public: // should be private sl@0: #endif sl@0: sl@0: sub_array (T* base, sl@0: const size_type* extents, sl@0: const index* strides, sl@0: const index* index_base) : sl@0: super_type(base,extents,strides,index_base) { sl@0: } sl@0: sl@0: }; sl@0: sl@0: } // namespace multi_array sl@0: } // namespace detail sl@0: // sl@0: // traits classes to get sub_array types sl@0: // sl@0: template sl@0: class subarray_gen { sl@0: typedef typename Array::element element; sl@0: public: sl@0: typedef boost::detail::multi_array::sub_array type; sl@0: }; sl@0: sl@0: template sl@0: class const_subarray_gen { sl@0: typedef typename Array::element element; sl@0: public: sl@0: typedef boost::detail::multi_array::const_sub_array type; sl@0: }; sl@0: } // namespace boost sl@0: sl@0: #endif // SUBARRAY_RG071801_HPP