|
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 SUBARRAY_RG071801_HPP |
|
14 #define SUBARRAY_RG071801_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 |
|
29 namespace boost { |
|
30 namespace detail { |
|
31 namespace 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. |
|
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> |
|
41 { |
|
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; |
|
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 detail::multi_array::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 #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_); |
|
107 } |
|
108 |
|
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()); |
|
112 } |
|
113 |
|
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; |
|
119 } |
|
120 |
|
121 template <typename OPtr> |
|
122 bool operator!=(const const_sub_array<T,NumDims,OPtr>& rhs) const { |
|
123 return !(*this == rhs); |
|
124 } |
|
125 |
|
126 template <typename OPtr> |
|
127 bool operator>(const const_sub_array<T,NumDims,OPtr>& rhs) const { |
|
128 return rhs < *this; |
|
129 } |
|
130 |
|
131 template <typename OPtr> |
|
132 bool operator<=(const const_sub_array<T,NumDims,OPtr>& rhs) const { |
|
133 return !(*this > rhs); |
|
134 } |
|
135 |
|
136 template <typename OPtr> |
|
137 bool operator>=(const const_sub_array<T,NumDims,OPtr>& rhs) const { |
|
138 return !(*this < rhs); |
|
139 } |
|
140 |
|
141 const_iterator begin() const { |
|
142 return const_iterator(*index_bases(),origin(), |
|
143 shape(),strides(),index_bases()); |
|
144 } |
|
145 |
|
146 const_iterator end() const { |
|
147 return const_iterator(*index_bases()+(index)*shape(),origin(), |
|
148 shape(),strides(),index_bases()); |
|
149 } |
|
150 |
|
151 const_reverse_iterator rbegin() const { |
|
152 return const_reverse_iterator(end()); |
|
153 } |
|
154 |
|
155 const_reverse_iterator rend() const { |
|
156 return const_reverse_iterator(begin()); |
|
157 } |
|
158 |
|
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_; } |
|
167 |
|
168 size_type num_elements() const { |
|
169 return std::accumulate(shape(),shape() + num_dimensions(), |
|
170 size_type(1), std::multiplies<size_type>()); |
|
171 } |
|
172 |
|
173 |
|
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 |
|
181 |
|
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) { |
|
188 } |
|
189 |
|
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&); |
|
197 }; |
|
198 |
|
199 |
|
200 // |
|
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*> |
|
207 { |
|
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; |
|
219 |
|
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; |
|
224 }; |
|
225 |
|
226 template <std::size_t NDims> |
|
227 struct array_view { |
|
228 typedef boost::detail::multi_array::multi_array_view<T,NDims> type; |
|
229 }; |
|
230 |
|
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> >(); |
|
236 |
|
237 // make sure the dimensions agree |
|
238 assert(other.num_dimensions() == this->num_dimensions()); |
|
239 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; |
|
244 } |
|
245 |
|
246 |
|
247 sub_array& operator=(const sub_array& other) { |
|
248 if (&other != this) { |
|
249 // make sure the dimensions agree |
|
250 assert(other.num_dimensions() == this->num_dimensions()); |
|
251 assert(std::equal(other.shape(),other.shape()+this->num_dimensions(), |
|
252 this->shape())); |
|
253 // iterator-based copy |
|
254 std::copy(other.begin(),other.end(),begin()); |
|
255 } |
|
256 return *this; |
|
257 } |
|
258 |
|
259 T* origin() { return this->base_; } |
|
260 const T* origin() const { return this->base_; } |
|
261 |
|
262 reference operator[](index idx) { |
|
263 return super_type::access(boost::type<reference>(), |
|
264 idx,this->base_,this->shape(),this->strides(), |
|
265 this->index_bases()); |
|
266 } |
|
267 |
|
268 // see generate_array_view in base.hpp |
|
269 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 |
|
270 template <int NDims> |
|
271 #else |
|
272 template <int NumDims, int NDims> // else ICE |
|
273 #endif // BOOST_MSVC |
|
274 typename array_view<NDims>::type |
|
275 operator[](const boost::detail::multi_array:: |
|
276 index_gen<NumDims,NDims>& indices) { |
|
277 typedef typename array_view<NDims>::type return_type; |
|
278 return |
|
279 super_type::generate_array_view(boost::type<return_type>(), |
|
280 indices, |
|
281 this->shape(), |
|
282 this->strides(), |
|
283 this->index_bases(), |
|
284 origin()); |
|
285 } |
|
286 |
|
287 template <class IndexList> |
|
288 element& operator()(const IndexList& indices) { |
|
289 boost::function_requires< |
|
290 detail::multi_array::CollectionConcept<IndexList> >(); |
|
291 return super_type::access_element(boost::type<element&>(), |
|
292 indices,origin(), |
|
293 this->shape(),this->strides(), |
|
294 this->index_bases()); |
|
295 } |
|
296 |
|
297 iterator begin() { |
|
298 return iterator(*this->index_bases(),origin(), |
|
299 this->shape(),this->strides(),this->index_bases()); |
|
300 } |
|
301 |
|
302 iterator end() { |
|
303 return iterator(*this->index_bases()+(index)*this->shape(),origin(), |
|
304 this->shape(),this->strides(),this->index_bases()); |
|
305 } |
|
306 |
|
307 // RG - rbegin() and rend() written naively to thwart MSVC ICE. |
|
308 reverse_iterator rbegin() { |
|
309 reverse_iterator ri(end()); |
|
310 return ri; |
|
311 } |
|
312 |
|
313 reverse_iterator rend() { |
|
314 reverse_iterator ri(begin()); |
|
315 return ri; |
|
316 } |
|
317 |
|
318 // |
|
319 // proxies |
|
320 // |
|
321 |
|
322 template <class IndexList> |
|
323 const element& operator()(const IndexList& indices) const { |
|
324 boost::function_requires< |
|
325 detail::multi_array::CollectionConcept<IndexList> >(); |
|
326 return super_type::operator()(indices); |
|
327 } |
|
328 |
|
329 const_reference operator[](index idx) const { |
|
330 return super_type::operator[](idx); |
|
331 } |
|
332 |
|
333 // see generate_array_view in base.hpp |
|
334 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 |
|
335 template <int NDims> |
|
336 #else |
|
337 template <int NumDims, int NDims> // else ICE |
|
338 #endif // BOOST_MSVC |
|
339 typename const_array_view<NDims>::type |
|
340 operator[](const boost::detail::multi_array:: |
|
341 index_gen<NumDims,NDims>& indices) |
|
342 const { |
|
343 return super_type::operator[](indices); |
|
344 } |
|
345 |
|
346 const_iterator begin() const { |
|
347 return super_type::begin(); |
|
348 } |
|
349 |
|
350 const_iterator end() const { |
|
351 return super_type::end(); |
|
352 } |
|
353 |
|
354 const_reverse_iterator rbegin() const { |
|
355 return super_type::rbegin(); |
|
356 } |
|
357 |
|
358 const_reverse_iterator rend() const { |
|
359 return super_type::rend(); |
|
360 } |
|
361 |
|
362 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
|
363 private: |
|
364 template <typename,std::size_t> friend class value_accessor_n; |
|
365 #else |
|
366 public: // should be private |
|
367 #endif |
|
368 |
|
369 sub_array (T* base, |
|
370 const size_type* extents, |
|
371 const index* strides, |
|
372 const index* index_base) : |
|
373 super_type(base,extents,strides,index_base) { |
|
374 } |
|
375 |
|
376 }; |
|
377 |
|
378 } // namespace multi_array |
|
379 } // namespace detail |
|
380 // |
|
381 // traits classes to get sub_array types |
|
382 // |
|
383 template <typename Array, int N> |
|
384 class subarray_gen { |
|
385 typedef typename Array::element element; |
|
386 public: |
|
387 typedef boost::detail::multi_array::sub_array<element,N> type; |
|
388 }; |
|
389 |
|
390 template <typename Array, int N> |
|
391 class const_subarray_gen { |
|
392 typedef typename Array::element element; |
|
393 public: |
|
394 typedef boost::detail::multi_array::const_sub_array<element,N> type; |
|
395 }; |
|
396 } // namespace boost |
|
397 |
|
398 #endif // SUBARRAY_RG071801_HPP |