fix doc example typo
[boost.git] / boost / multi_array / subarray.hpp
blobc336f82d1e54d80899d1b5d55afa17e5c7e9e695
1 // Copyright 2002 The Trustees of Indiana University.
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 // Boost.MultiArray Library
8 // Authors: Ronald Garcia
9 // Jeremy Siek
10 // Andrew Lumsdaine
11 // See http://www.boost.org/libs/multi_array for documentation.
13 #ifndef SUBARRAY_RG071801_HPP
14 #define SUBARRAY_RG071801_HPP
17 // subarray.hpp - used to implement standard operator[] on
18 // multi_arrays
21 #include "boost/multi_array/base.hpp"
22 #include "boost/multi_array/concept_checks.hpp"
23 #include "boost/limits.hpp"
24 #include "boost/type.hpp"
25 #include <algorithm>
26 #include <cstddef>
27 #include <functional>
29 namespace boost {
30 namespace detail {
31 namespace multi_array {
34 // const_sub_array
35 // multi_array's proxy class to allow multiple overloads of
36 // operator[] in order to provide a clean multi-dimensional array
37 // interface.
38 template <typename T, std::size_t NumDims, typename TPtr>
39 class const_sub_array :
40 public boost::detail::multi_array::multi_array_impl_base<T,NumDims>
42 typedef boost::detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
43 public:
44 typedef typename super_type::value_type value_type;
45 typedef typename super_type::const_reference const_reference;
46 typedef typename super_type::const_iterator const_iterator;
47 typedef typename super_type::const_reverse_iterator const_reverse_iterator;
48 typedef typename super_type::element element;
49 typedef typename super_type::size_type size_type;
50 typedef typename super_type::difference_type difference_type;
51 typedef typename super_type::index index;
52 typedef typename super_type::extent_range extent_range;
54 // template typedefs
55 template <std::size_t NDims>
56 struct const_array_view {
57 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
60 template <std::size_t NDims>
61 struct array_view {
62 typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
65 // Allow default copy constructor as well.
67 template <typename OPtr>
68 const_sub_array (const const_sub_array<T,NumDims,OPtr>& rhs) :
69 base_(rhs.base_), extents_(rhs.extents_), strides_(rhs.strides_),
70 index_base_(rhs.index_base_) {
73 // const_sub_array always returns const types, regardless of its own
74 // constness.
75 const_reference operator[](index idx) const {
76 return super_type::access(boost::type<const_reference>(),
77 idx,base_,shape(),strides(),index_bases());
80 template <typename IndexList>
81 const element& operator()(const IndexList& indices) const {
82 boost::function_requires<
83 detail::multi_array::CollectionConcept<IndexList> >();
84 return super_type::access_element(boost::type<const element&>(),
85 indices,origin(),
86 shape(),strides(),index_bases());
89 // see generate_array_view in base.hpp
90 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
91 template <int NDims>
92 #else
93 template <int NumDims, int NDims> // else ICE
94 #endif // BOOST_MSVC
95 typename const_array_view<NDims>::type
96 operator[](const boost::detail::multi_array::
97 index_gen<NumDims,NDims>& indices)
98 const {
99 typedef typename const_array_view<NDims>::type return_type;
100 return
101 super_type::generate_array_view(boost::type<return_type>(),
102 indices,
103 shape(),
104 strides(),
105 index_bases(),
106 base_);
109 template <typename OPtr>
110 bool operator<(const const_sub_array<T,NumDims,OPtr>& rhs) const {
111 return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
114 template <typename OPtr>
115 bool operator==(const const_sub_array<T,NumDims,OPtr>& rhs) const {
116 if(std::equal(shape(),shape()+num_dimensions(),rhs.shape()))
117 return std::equal(begin(),end(),rhs.begin());
118 else return false;
121 template <typename OPtr>
122 bool operator!=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
123 return !(*this == rhs);
126 template <typename OPtr>
127 bool operator>(const const_sub_array<T,NumDims,OPtr>& rhs) const {
128 return rhs < *this;
131 template <typename OPtr>
132 bool operator<=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
133 return !(*this > rhs);
136 template <typename OPtr>
137 bool operator>=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
138 return !(*this < rhs);
141 const_iterator begin() const {
142 return const_iterator(*index_bases(),origin(),
143 shape(),strides(),index_bases());
146 const_iterator end() const {
147 return const_iterator(*index_bases()+(index)*shape(),origin(),
148 shape(),strides(),index_bases());
151 const_reverse_iterator rbegin() const {
152 return const_reverse_iterator(end());
155 const_reverse_iterator rend() const {
156 return const_reverse_iterator(begin());
159 TPtr origin() const { return base_; }
160 size_type size() const { return extents_[0]; }
161 size_type max_size() const { return num_elements(); }
162 bool empty() const { return size() == 0; }
163 size_type num_dimensions() const { return NumDims; }
164 const size_type* shape() const { return extents_; }
165 const index* strides() const { return strides_; }
166 const index* index_bases() const { return index_base_; }
168 size_type num_elements() const {
169 return std::accumulate(shape(),shape() + num_dimensions(),
170 size_type(1), std::multiplies<size_type>());
174 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
175 protected:
176 template <typename,std::size_t> friend class value_accessor_n;
177 template <typename,std::size_t,typename> friend class const_sub_array;
178 #else
179 public: // Should be protected
180 #endif
182 const_sub_array (TPtr base,
183 const size_type* extents,
184 const index* strides,
185 const index* index_base) :
186 base_(base), extents_(extents), strides_(strides),
187 index_base_(index_base) {
190 TPtr base_;
191 const size_type* extents_;
192 const index* strides_;
193 const index* index_base_;
194 private:
195 // const_sub_array cannot be assigned to (no deep copies!)
196 const_sub_array& operator=(const const_sub_array&);
201 // sub_array
202 // multi_array's proxy class to allow multiple overloads of
203 // operator[] in order to provide a clean multi-dimensional array
204 // interface.
205 template <typename T, std::size_t NumDims>
206 class sub_array : public const_sub_array<T,NumDims,T*>
208 typedef const_sub_array<T,NumDims,T*> super_type;
209 public:
210 typedef typename super_type::element element;
211 typedef typename super_type::reference reference;
212 typedef typename super_type::index index;
213 typedef typename super_type::size_type size_type;
214 typedef typename super_type::iterator iterator;
215 typedef typename super_type::reverse_iterator reverse_iterator;
216 typedef typename super_type::const_reference const_reference;
217 typedef typename super_type::const_iterator const_iterator;
218 typedef typename super_type::const_reverse_iterator const_reverse_iterator;
220 // template typedefs
221 template <std::size_t NDims>
222 struct const_array_view {
223 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
226 template <std::size_t NDims>
227 struct array_view {
228 typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
231 // Assignment from other ConstMultiArray types.
232 template <typename ConstMultiArray>
233 sub_array& operator=(const ConstMultiArray& other) {
234 function_requires< boost::detail::multi_array::ConstMultiArrayConcept<
235 ConstMultiArray, NumDims> >();
237 // make sure the dimensions agree
238 BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
239 BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(),
240 this->shape()));
241 // iterator-based copy
242 std::copy(other.begin(),other.end(),begin());
243 return *this;
247 sub_array& operator=(const sub_array& other) {
248 if (&other != this) {
249 // make sure the dimensions agree
250 BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
251 BOOST_ASSERT(std::equal(other.shape(),
252 other.shape()+this->num_dimensions(),
253 this->shape()));
254 // iterator-based copy
255 std::copy(other.begin(),other.end(),begin());
257 return *this;
260 T* origin() { return this->base_; }
261 const T* origin() const { return this->base_; }
263 reference operator[](index idx) {
264 return super_type::access(boost::type<reference>(),
265 idx,this->base_,this->shape(),this->strides(),
266 this->index_bases());
269 // see generate_array_view in base.hpp
270 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
271 template <int NDims>
272 #else
273 template <int NumDims, int NDims> // else ICE
274 #endif // BOOST_MSVC
275 typename array_view<NDims>::type
276 operator[](const boost::detail::multi_array::
277 index_gen<NumDims,NDims>& indices) {
278 typedef typename array_view<NDims>::type return_type;
279 return
280 super_type::generate_array_view(boost::type<return_type>(),
281 indices,
282 this->shape(),
283 this->strides(),
284 this->index_bases(),
285 origin());
288 template <class IndexList>
289 element& operator()(const IndexList& indices) {
290 boost::function_requires<
291 detail::multi_array::CollectionConcept<IndexList> >();
292 return super_type::access_element(boost::type<element&>(),
293 indices,origin(),
294 this->shape(),this->strides(),
295 this->index_bases());
298 iterator begin() {
299 return iterator(*this->index_bases(),origin(),
300 this->shape(),this->strides(),this->index_bases());
303 iterator end() {
304 return iterator(*this->index_bases()+(index)*this->shape(),origin(),
305 this->shape(),this->strides(),this->index_bases());
308 // RG - rbegin() and rend() written naively to thwart MSVC ICE.
309 reverse_iterator rbegin() {
310 reverse_iterator ri(end());
311 return ri;
314 reverse_iterator rend() {
315 reverse_iterator ri(begin());
316 return ri;
320 // proxies
323 template <class IndexList>
324 const element& operator()(const IndexList& indices) const {
325 boost::function_requires<
326 detail::multi_array::CollectionConcept<IndexList> >();
327 return super_type::operator()(indices);
330 const_reference operator[](index idx) const {
331 return super_type::operator[](idx);
334 // see generate_array_view in base.hpp
335 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
336 template <int NDims>
337 #else
338 template <int NumDims, int NDims> // else ICE
339 #endif // BOOST_MSVC
340 typename const_array_view<NDims>::type
341 operator[](const boost::detail::multi_array::
342 index_gen<NumDims,NDims>& indices)
343 const {
344 return super_type::operator[](indices);
347 const_iterator begin() const {
348 return super_type::begin();
351 const_iterator end() const {
352 return super_type::end();
355 const_reverse_iterator rbegin() const {
356 return super_type::rbegin();
359 const_reverse_iterator rend() const {
360 return super_type::rend();
363 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
364 private:
365 template <typename,std::size_t> friend class value_accessor_n;
366 #else
367 public: // should be private
368 #endif
370 sub_array (T* base,
371 const size_type* extents,
372 const index* strides,
373 const index* index_base) :
374 super_type(base,extents,strides,index_base) {
379 } // namespace multi_array
380 } // namespace detail
382 // traits classes to get sub_array types
384 template <typename Array, int N>
385 class subarray_gen {
386 typedef typename Array::element element;
387 public:
388 typedef boost::detail::multi_array::sub_array<element,N> type;
391 template <typename Array, int N>
392 class const_subarray_gen {
393 typedef typename Array::element element;
394 public:
395 typedef boost::detail::multi_array::const_sub_array<element,N> type;
397 } // namespace boost
399 #endif // SUBARRAY_RG071801_HPP