1// Copyright 2002 The Trustees of Indiana University.
2
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)
6
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.
12
13#ifndef BOOST_MULTI_ARRAY_SUBARRAY_HPP
14#define BOOST_MULTI_ARRAY_SUBARRAY_HPP
15
16//
17// subarray.hpp - used to implement standard operator[] on
18// multi_arrays
19//
20
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>
28
29namespace boost {
30namespace detail {
31namespace multi_array {
32
33//
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.
38template <typename T, std::size_t NumDims, typename TPtr>
39class const_sub_array :
40 public boost::detail::multi_array::multi_array_impl_base<T,NumDims>
41{
42 typedef boost::detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
43public:
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;
53
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;
58 };
59
60 template <std::size_t NDims>
61 struct array_view {
62 typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
63 };
64
65 // Allow default copy constructor as well.
66
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_) {
71 }
72
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());
78 }
79
80 template <typename IndexList>
81 const element& operator()(const IndexList& indices) const {
82 boost::function_requires<
83 CollectionConcept<IndexList> >();
84 return super_type::access_element(boost::type<const element&>(),
85 indices,origin(),
86 shape(),strides(),index_bases());
87 }
88
89 // see generate_array_view in base.hpp
90 template <int NDims>
91 typename const_array_view<NDims>::type
92 operator[](const boost::detail::multi_array::
93 index_gen<NumDims,NDims>& indices)
94 const {
95 typedef typename const_array_view<NDims>::type return_type;
96 return
97 super_type::generate_array_view(boost::type<return_type>(),
98 indices,
99 shape(),
100 strides(),
101 index_bases(),
102 base_);
103 }
104
105 template <typename OPtr>
106 bool operator<(const const_sub_array<T,NumDims,OPtr>& rhs) const {
107 return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
108 }
109
110 template <typename OPtr>
111 bool operator==(const const_sub_array<T,NumDims,OPtr>& rhs) const {
112 if(std::equal(shape(),shape()+num_dimensions(),rhs.shape()))
113 return std::equal(begin(),end(),rhs.begin());
114 else return false;
115 }
116
117 template <typename OPtr>
118 bool operator!=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
119 return !(*this == rhs);
120 }
121
122 template <typename OPtr>
123 bool operator>(const const_sub_array<T,NumDims,OPtr>& rhs) const {
124 return rhs < *this;
125 }
126
127 template <typename OPtr>
128 bool operator<=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
129 return !(*this > rhs);
130 }
131
132 template <typename OPtr>
133 bool operator>=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
134 return !(*this < rhs);
135 }
136
137 const_iterator begin() const {
138 return const_iterator(*index_bases(),origin(),
139 shape(),strides(),index_bases());
140 }
141
142 const_iterator end() const {
143 return const_iterator(*index_bases()+(index)*shape(),origin(),
144 shape(),strides(),index_bases());
145 }
146
147 const_reverse_iterator rbegin() const {
148 return const_reverse_iterator(end());
149 }
150
151 const_reverse_iterator rend() const {
152 return const_reverse_iterator(begin());
153 }
154
155 TPtr origin() const { return base_; }
156 size_type size() const { return extents_[0]; }
157 size_type max_size() const { return num_elements(); }
158 bool empty() const { return size() == 0; }
159 size_type num_dimensions() const { return NumDims; }
160 const size_type* shape() const { return extents_; }
161 const index* strides() const { return strides_; }
162 const index* index_bases() const { return index_base_; }
163
164 size_type num_elements() const {
165 return std::accumulate(shape(),shape() + num_dimensions(),
166 size_type(1), std::multiplies<size_type>());
167 }
168
169
170#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
171protected:
172 template <typename,std::size_t> friend class value_accessor_n;
173 template <typename,std::size_t,typename> friend class const_sub_array;
174#else
175public: // Should be protected
176#endif
177
178 const_sub_array (TPtr base,
179 const size_type* extents,
180 const index* strides,
181 const index* index_base) :
182 base_(base), extents_(extents), strides_(strides),
183 index_base_(index_base) {
184 }
185
186 TPtr base_;
187 const size_type* extents_;
188 const index* strides_;
189 const index* index_base_;
190private:
191 // const_sub_array cannot be assigned to (no deep copies!)
192 const_sub_array& operator=(const const_sub_array&);
193};
194
195
196//
197// sub_array
198// multi_array's proxy class to allow multiple overloads of
199// operator[] in order to provide a clean multi-dimensional array
200// interface.
201template <typename T, std::size_t NumDims>
202class sub_array : public const_sub_array<T,NumDims,T*>
203{
204 typedef const_sub_array<T,NumDims,T*> super_type;
205public:
206 typedef typename super_type::element element;
207 typedef typename super_type::reference reference;
208 typedef typename super_type::index index;
209 typedef typename super_type::size_type size_type;
210 typedef typename super_type::iterator iterator;
211 typedef typename super_type::reverse_iterator reverse_iterator;
212 typedef typename super_type::const_reference const_reference;
213 typedef typename super_type::const_iterator const_iterator;
214 typedef typename super_type::const_reverse_iterator const_reverse_iterator;
215
216 // template typedefs
217 template <std::size_t NDims>
218 struct const_array_view {
219 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
220 };
221
222 template <std::size_t NDims>
223 struct array_view {
224 typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
225 };
226
227 // Assignment from other ConstMultiArray types.
228 template <typename ConstMultiArray>
229 sub_array& operator=(const ConstMultiArray& other) {
230 function_requires< boost::multi_array_concepts::ConstMultiArrayConcept<
231 ConstMultiArray, NumDims> >();
232
233 // make sure the dimensions agree
234 BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
235 BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(),
236 this->shape()));
237 // iterator-based copy
238 std::copy(other.begin(),other.end(),begin());
239 return *this;
240 }
241
242
243 sub_array& operator=(const sub_array& other) {
244 if (&other != this) {
245 // make sure the dimensions agree
246 BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
247 BOOST_ASSERT(std::equal(other.shape(),
248 other.shape()+this->num_dimensions(),
249 this->shape()));
250 // iterator-based copy
251 std::copy(other.begin(),other.end(),begin());
252 }
253 return *this;
254 }
255
256 T* origin() { return this->base_; }
257 const T* origin() const { return this->base_; }
258
259 reference operator[](index idx) {
260 return super_type::access(boost::type<reference>(),
261 idx,this->base_,this->shape(),this->strides(),
262 this->index_bases());
263 }
264
265 // see generate_array_view in base.hpp
266 template <int NDims>
267 typename array_view<NDims>::type
268 operator[](const boost::detail::multi_array::
269 index_gen<NumDims,NDims>& indices) {
270 typedef typename array_view<NDims>::type return_type;
271 return
272 super_type::generate_array_view(boost::type<return_type>(),
273 indices,
274 this->shape(),
275 this->strides(),
276 this->index_bases(),
277 origin());
278 }
279
280 template <class IndexList>
281 element& operator()(const IndexList& indices) {
282 boost::function_requires<
283 CollectionConcept<IndexList> >();
284 return super_type::access_element(boost::type<element&>(),
285 indices,origin(),
286 this->shape(),this->strides(),
287 this->index_bases());
288 }
289
290 iterator begin() {
291 return iterator(*this->index_bases(),origin(),
292 this->shape(),this->strides(),this->index_bases());
293 }
294
295 iterator end() {
296 return iterator(*this->index_bases()+(index)*this->shape(),origin(),
297 this->shape(),this->strides(),this->index_bases());
298 }
299
300 // RG - rbegin() and rend() written naively to thwart MSVC ICE.
301 reverse_iterator rbegin() {
302 reverse_iterator ri(end());
303 return ri;
304 }
305
306 reverse_iterator rend() {
307 reverse_iterator ri(begin());
308 return ri;
309 }
310
311 //
312 // proxies
313 //
314
315 template <class IndexList>
316 const element& operator()(const IndexList& indices) const {
317 boost::function_requires<
318 CollectionConcept<IndexList> >();
319 return super_type::operator()(indices);
320 }
321
322 const_reference operator[](index idx) const {
323 return super_type::operator[](idx);
324 }
325
326 // see generate_array_view in base.hpp
327 template <int NDims>
328 typename const_array_view<NDims>::type
329 operator[](const boost::detail::multi_array::
330 index_gen<NumDims,NDims>& indices)
331 const {
332 return super_type::operator[](indices);
333 }
334
335 const_iterator begin() const {
336 return super_type::begin();
337 }
338
339 const_iterator end() const {
340 return super_type::end();
341 }
342
343 const_reverse_iterator rbegin() const {
344 return super_type::rbegin();
345 }
346
347 const_reverse_iterator rend() const {
348 return super_type::rend();
349 }
350
351#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
352private:
353 template <typename,std::size_t> friend class value_accessor_n;
354#else
355public: // should be private
356#endif
357
358 sub_array (T* base,
359 const size_type* extents,
360 const index* strides,
361 const index* index_base) :
362 super_type(base,extents,strides,index_base) {
363 }
364
365};
366
367} // namespace multi_array
368} // namespace detail
369//
370// traits classes to get sub_array types
371//
372template <typename Array, int N>
373class subarray_gen {
374 typedef typename Array::element element;
375public:
376 typedef boost::detail::multi_array::sub_array<element,N> type;
377};
378
379template <typename Array, int N>
380class const_subarray_gen {
381 typedef typename Array::element element;
382public:
383 typedef boost::detail::multi_array::const_sub_array<element,N> type;
384};
385} // namespace boost
386
387#endif
388

source code of include/boost/multi_array/subarray.hpp