Chris@16
|
1 // Copyright 2002 The Trustees of Indiana University.
|
Chris@16
|
2
|
Chris@16
|
3 // Use, modification and distribution is subject to the Boost Software
|
Chris@16
|
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6
|
Chris@16
|
7 // Boost.MultiArray Library
|
Chris@16
|
8 // Authors: Ronald Garcia
|
Chris@16
|
9 // Jeremy Siek
|
Chris@16
|
10 // Andrew Lumsdaine
|
Chris@16
|
11 // See http://www.boost.org/libs/multi_array for documentation.
|
Chris@16
|
12
|
Chris@16
|
13 #ifndef BOOST_MULTI_ARRAY_REF_RG071801_HPP
|
Chris@16
|
14 #define BOOST_MULTI_ARRAY_REF_RG071801_HPP
|
Chris@16
|
15
|
Chris@16
|
16 //
|
Chris@16
|
17 // multi_array_ref.hpp - code for creating "views" of array data.
|
Chris@16
|
18 //
|
Chris@16
|
19
|
Chris@16
|
20 #include "boost/multi_array/base.hpp"
|
Chris@16
|
21 #include "boost/multi_array/collection_concept.hpp"
|
Chris@16
|
22 #include "boost/multi_array/concept_checks.hpp"
|
Chris@16
|
23 #include "boost/multi_array/iterator.hpp"
|
Chris@16
|
24 #include "boost/multi_array/storage_order.hpp"
|
Chris@16
|
25 #include "boost/multi_array/subarray.hpp"
|
Chris@16
|
26 #include "boost/multi_array/view.hpp"
|
Chris@16
|
27 #include "boost/multi_array/algorithm.hpp"
|
Chris@16
|
28 #include "boost/type_traits/is_integral.hpp"
|
Chris@16
|
29 #include "boost/utility/enable_if.hpp"
|
Chris@16
|
30 #include "boost/array.hpp"
|
Chris@16
|
31 #include "boost/concept_check.hpp"
|
Chris@16
|
32 #include "boost/functional.hpp"
|
Chris@16
|
33 #include "boost/limits.hpp"
|
Chris@16
|
34 #include <algorithm>
|
Chris@16
|
35 #include <cstddef>
|
Chris@16
|
36 #include <functional>
|
Chris@16
|
37 #include <numeric>
|
Chris@16
|
38
|
Chris@16
|
39 namespace boost {
|
Chris@16
|
40
|
Chris@16
|
41 template <typename T, std::size_t NumDims,
|
Chris@16
|
42 typename TPtr = const T*
|
Chris@16
|
43 >
|
Chris@16
|
44 class const_multi_array_ref :
|
Chris@16
|
45 public detail::multi_array::multi_array_impl_base<T,NumDims>
|
Chris@16
|
46 {
|
Chris@16
|
47 typedef detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
|
Chris@16
|
48 public:
|
Chris@16
|
49 typedef typename super_type::value_type value_type;
|
Chris@16
|
50 typedef typename super_type::const_reference const_reference;
|
Chris@16
|
51 typedef typename super_type::const_iterator const_iterator;
|
Chris@16
|
52 typedef typename super_type::const_reverse_iterator const_reverse_iterator;
|
Chris@16
|
53 typedef typename super_type::element element;
|
Chris@16
|
54 typedef typename super_type::size_type size_type;
|
Chris@16
|
55 typedef typename super_type::difference_type difference_type;
|
Chris@16
|
56 typedef typename super_type::index index;
|
Chris@16
|
57 typedef typename super_type::extent_range extent_range;
|
Chris@16
|
58 typedef general_storage_order<NumDims> storage_order_type;
|
Chris@16
|
59
|
Chris@16
|
60 // template typedefs
|
Chris@16
|
61 template <std::size_t NDims>
|
Chris@16
|
62 struct const_array_view {
|
Chris@16
|
63 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
|
Chris@16
|
64 };
|
Chris@16
|
65
|
Chris@16
|
66 template <std::size_t NDims>
|
Chris@16
|
67 struct array_view {
|
Chris@16
|
68 typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
|
Chris@16
|
69 };
|
Chris@16
|
70
|
Chris@16
|
71 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
Chris@16
|
72 // make const_multi_array_ref a friend of itself
|
Chris@16
|
73 template <typename,std::size_t,typename>
|
Chris@16
|
74 friend class const_multi_array_ref;
|
Chris@16
|
75 #endif
|
Chris@16
|
76
|
Chris@16
|
77 // This ensures that const_multi_array_ref types with different TPtr
|
Chris@16
|
78 // types can convert to each other
|
Chris@16
|
79 template <typename OPtr>
|
Chris@16
|
80 const_multi_array_ref(const const_multi_array_ref<T,NumDims,OPtr>& other)
|
Chris@16
|
81 : base_(other.base_), storage_(other.storage_),
|
Chris@16
|
82 extent_list_(other.extent_list_),
|
Chris@16
|
83 stride_list_(other.stride_list_),
|
Chris@16
|
84 index_base_list_(other.index_base_list_),
|
Chris@16
|
85 origin_offset_(other.origin_offset_),
|
Chris@16
|
86 directional_offset_(other.directional_offset_),
|
Chris@16
|
87 num_elements_(other.num_elements_) { }
|
Chris@16
|
88
|
Chris@16
|
89 template <typename ExtentList>
|
Chris@16
|
90 explicit const_multi_array_ref(TPtr base, const ExtentList& extents) :
|
Chris@16
|
91 base_(base), storage_(c_storage_order()) {
|
Chris@16
|
92 boost::function_requires<
|
Chris@16
|
93 CollectionConcept<ExtentList> >();
|
Chris@16
|
94
|
Chris@16
|
95 index_base_list_.assign(0);
|
Chris@16
|
96 init_multi_array_ref(extents.begin());
|
Chris@16
|
97 }
|
Chris@16
|
98
|
Chris@16
|
99 template <typename ExtentList>
|
Chris@16
|
100 explicit const_multi_array_ref(TPtr base, const ExtentList& extents,
|
Chris@16
|
101 const general_storage_order<NumDims>& so) :
|
Chris@16
|
102 base_(base), storage_(so) {
|
Chris@16
|
103 boost::function_requires<
|
Chris@16
|
104 CollectionConcept<ExtentList> >();
|
Chris@16
|
105
|
Chris@16
|
106 index_base_list_.assign(0);
|
Chris@16
|
107 init_multi_array_ref(extents.begin());
|
Chris@16
|
108 }
|
Chris@16
|
109
|
Chris@16
|
110 explicit const_multi_array_ref(TPtr base,
|
Chris@16
|
111 const detail::multi_array::
|
Chris@16
|
112 extent_gen<NumDims>& ranges) :
|
Chris@16
|
113 base_(base), storage_(c_storage_order()) {
|
Chris@16
|
114
|
Chris@16
|
115 init_from_extent_gen(ranges);
|
Chris@16
|
116 }
|
Chris@16
|
117
|
Chris@16
|
118 explicit const_multi_array_ref(TPtr base,
|
Chris@16
|
119 const detail::multi_array::
|
Chris@16
|
120 extent_gen<NumDims>& ranges,
|
Chris@16
|
121 const general_storage_order<NumDims>& so) :
|
Chris@16
|
122 base_(base), storage_(so) {
|
Chris@16
|
123
|
Chris@16
|
124 init_from_extent_gen(ranges);
|
Chris@16
|
125 }
|
Chris@16
|
126
|
Chris@16
|
127 template <class InputIterator>
|
Chris@16
|
128 void assign(InputIterator begin, InputIterator end) {
|
Chris@16
|
129 boost::function_requires<InputIteratorConcept<InputIterator> >();
|
Chris@16
|
130
|
Chris@16
|
131 InputIterator in_iter = begin;
|
Chris@16
|
132 T* out_iter = base_;
|
Chris@16
|
133 std::size_t copy_count=0;
|
Chris@16
|
134 while (in_iter != end && copy_count < num_elements_) {
|
Chris@16
|
135 *out_iter++ = *in_iter++;
|
Chris@16
|
136 copy_count++;
|
Chris@16
|
137 }
|
Chris@16
|
138 }
|
Chris@16
|
139
|
Chris@16
|
140 template <class BaseList>
|
Chris@16
|
141 #ifdef BOOST_NO_SFINAE
|
Chris@16
|
142 void
|
Chris@16
|
143 #else
|
Chris@16
|
144 typename
|
Chris@16
|
145 disable_if<typename boost::is_integral<BaseList>::type,void >::type
|
Chris@16
|
146 #endif // BOOST_NO_SFINAE
|
Chris@16
|
147 reindex(const BaseList& values) {
|
Chris@16
|
148 boost::function_requires<
|
Chris@16
|
149 CollectionConcept<BaseList> >();
|
Chris@16
|
150 boost::detail::multi_array::
|
Chris@16
|
151 copy_n(values.begin(),num_dimensions(),index_base_list_.begin());
|
Chris@16
|
152 origin_offset_ =
|
Chris@16
|
153 this->calculate_origin_offset(stride_list_,extent_list_,
|
Chris@16
|
154 storage_,index_base_list_);
|
Chris@16
|
155 }
|
Chris@16
|
156
|
Chris@16
|
157 void reindex(index value) {
|
Chris@16
|
158 index_base_list_.assign(value);
|
Chris@16
|
159 origin_offset_ =
|
Chris@16
|
160 this->calculate_origin_offset(stride_list_,extent_list_,
|
Chris@16
|
161 storage_,index_base_list_);
|
Chris@16
|
162 }
|
Chris@16
|
163
|
Chris@16
|
164 template <typename SizeList>
|
Chris@16
|
165 void reshape(const SizeList& extents) {
|
Chris@16
|
166 boost::function_requires<
|
Chris@16
|
167 CollectionConcept<SizeList> >();
|
Chris@16
|
168 BOOST_ASSERT(num_elements_ ==
|
Chris@16
|
169 std::accumulate(extents.begin(),extents.end(),
|
Chris@16
|
170 size_type(1),std::multiplies<size_type>()));
|
Chris@16
|
171
|
Chris@16
|
172 std::copy(extents.begin(),extents.end(),extent_list_.begin());
|
Chris@16
|
173 this->compute_strides(stride_list_,extent_list_,storage_);
|
Chris@16
|
174
|
Chris@16
|
175 origin_offset_ =
|
Chris@16
|
176 this->calculate_origin_offset(stride_list_,extent_list_,
|
Chris@16
|
177 storage_,index_base_list_);
|
Chris@16
|
178 }
|
Chris@16
|
179
|
Chris@16
|
180 size_type num_dimensions() const { return NumDims; }
|
Chris@16
|
181
|
Chris@16
|
182 size_type size() const { return extent_list_.front(); }
|
Chris@16
|
183
|
Chris@16
|
184 // given reshaping functionality, this is the max possible size.
|
Chris@16
|
185 size_type max_size() const { return num_elements(); }
|
Chris@16
|
186
|
Chris@16
|
187 bool empty() const { return size() == 0; }
|
Chris@16
|
188
|
Chris@16
|
189 const size_type* shape() const {
|
Chris@16
|
190 return extent_list_.data();
|
Chris@16
|
191 }
|
Chris@16
|
192
|
Chris@16
|
193 const index* strides() const {
|
Chris@16
|
194 return stride_list_.data();
|
Chris@16
|
195 }
|
Chris@16
|
196
|
Chris@16
|
197 const element* origin() const { return base_+origin_offset_; }
|
Chris@16
|
198 const element* data() const { return base_; }
|
Chris@16
|
199
|
Chris@16
|
200 size_type num_elements() const { return num_elements_; }
|
Chris@16
|
201
|
Chris@16
|
202 const index* index_bases() const {
|
Chris@16
|
203 return index_base_list_.data();
|
Chris@16
|
204 }
|
Chris@16
|
205
|
Chris@16
|
206
|
Chris@16
|
207 const storage_order_type& storage_order() const {
|
Chris@16
|
208 return storage_;
|
Chris@16
|
209 }
|
Chris@16
|
210
|
Chris@16
|
211 template <typename IndexList>
|
Chris@16
|
212 const element& operator()(IndexList indices) const {
|
Chris@16
|
213 boost::function_requires<
|
Chris@16
|
214 CollectionConcept<IndexList> >();
|
Chris@16
|
215 return super_type::access_element(boost::type<const element&>(),
|
Chris@16
|
216 indices,origin(),
|
Chris@16
|
217 shape(),strides(),index_bases());
|
Chris@16
|
218 }
|
Chris@16
|
219
|
Chris@16
|
220 // Only allow const element access
|
Chris@16
|
221 const_reference operator[](index idx) const {
|
Chris@16
|
222 return super_type::access(boost::type<const_reference>(),
|
Chris@16
|
223 idx,origin(),
|
Chris@16
|
224 shape(),strides(),index_bases());
|
Chris@16
|
225 }
|
Chris@16
|
226
|
Chris@16
|
227 // see generate_array_view in base.hpp
|
Chris@16
|
228 template <int NDims>
|
Chris@16
|
229 typename const_array_view<NDims>::type
|
Chris@16
|
230 operator[](const detail::multi_array::
|
Chris@16
|
231 index_gen<NumDims,NDims>& indices)
|
Chris@16
|
232 const {
|
Chris@16
|
233 typedef typename const_array_view<NDims>::type return_type;
|
Chris@16
|
234 return
|
Chris@16
|
235 super_type::generate_array_view(boost::type<return_type>(),
|
Chris@16
|
236 indices,
|
Chris@16
|
237 shape(),
|
Chris@16
|
238 strides(),
|
Chris@16
|
239 index_bases(),
|
Chris@16
|
240 origin());
|
Chris@16
|
241 }
|
Chris@16
|
242
|
Chris@16
|
243 const_iterator begin() const {
|
Chris@16
|
244 return const_iterator(*index_bases(),origin(),
|
Chris@16
|
245 shape(),strides(),index_bases());
|
Chris@16
|
246 }
|
Chris@16
|
247
|
Chris@16
|
248 const_iterator end() const {
|
Chris@16
|
249 return const_iterator(*index_bases()+(index)*shape(),origin(),
|
Chris@16
|
250 shape(),strides(),index_bases());
|
Chris@16
|
251 }
|
Chris@16
|
252
|
Chris@16
|
253 const_reverse_iterator rbegin() const {
|
Chris@16
|
254 return const_reverse_iterator(end());
|
Chris@16
|
255 }
|
Chris@16
|
256
|
Chris@16
|
257 const_reverse_iterator rend() const {
|
Chris@16
|
258 return const_reverse_iterator(begin());
|
Chris@16
|
259 }
|
Chris@16
|
260
|
Chris@16
|
261
|
Chris@16
|
262 template <typename OPtr>
|
Chris@16
|
263 bool operator==(const
|
Chris@16
|
264 const_multi_array_ref<T,NumDims,OPtr>& rhs)
|
Chris@16
|
265 const {
|
Chris@16
|
266 if(std::equal(extent_list_.begin(),
|
Chris@16
|
267 extent_list_.end(),
|
Chris@16
|
268 rhs.extent_list_.begin()))
|
Chris@16
|
269 return std::equal(begin(),end(),rhs.begin());
|
Chris@16
|
270 else return false;
|
Chris@16
|
271 }
|
Chris@16
|
272
|
Chris@16
|
273 template <typename OPtr>
|
Chris@16
|
274 bool operator<(const
|
Chris@16
|
275 const_multi_array_ref<T,NumDims,OPtr>& rhs)
|
Chris@16
|
276 const {
|
Chris@16
|
277 return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
|
Chris@16
|
278 }
|
Chris@16
|
279
|
Chris@16
|
280 template <typename OPtr>
|
Chris@16
|
281 bool operator!=(const
|
Chris@16
|
282 const_multi_array_ref<T,NumDims,OPtr>& rhs)
|
Chris@16
|
283 const {
|
Chris@16
|
284 return !(*this == rhs);
|
Chris@16
|
285 }
|
Chris@16
|
286
|
Chris@16
|
287 template <typename OPtr>
|
Chris@16
|
288 bool operator>(const
|
Chris@16
|
289 const_multi_array_ref<T,NumDims,OPtr>& rhs)
|
Chris@16
|
290 const {
|
Chris@16
|
291 return rhs < *this;
|
Chris@16
|
292 }
|
Chris@16
|
293
|
Chris@16
|
294 template <typename OPtr>
|
Chris@16
|
295 bool operator<=(const
|
Chris@16
|
296 const_multi_array_ref<T,NumDims,OPtr>& rhs)
|
Chris@16
|
297 const {
|
Chris@16
|
298 return !(*this > rhs);
|
Chris@16
|
299 }
|
Chris@16
|
300
|
Chris@16
|
301 template <typename OPtr>
|
Chris@16
|
302 bool operator>=(const
|
Chris@16
|
303 const_multi_array_ref<T,NumDims,OPtr>& rhs)
|
Chris@16
|
304 const {
|
Chris@16
|
305 return !(*this < rhs);
|
Chris@16
|
306 }
|
Chris@16
|
307
|
Chris@16
|
308
|
Chris@16
|
309 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
Chris@16
|
310 protected:
|
Chris@16
|
311 #else
|
Chris@16
|
312 public:
|
Chris@16
|
313 #endif
|
Chris@16
|
314
|
Chris@16
|
315 typedef boost::array<size_type,NumDims> size_list;
|
Chris@16
|
316 typedef boost::array<index,NumDims> index_list;
|
Chris@16
|
317
|
Chris@16
|
318 // This is used by multi_array, which is a subclass of this
|
Chris@16
|
319 void set_base_ptr(TPtr new_base) { base_ = new_base; }
|
Chris@16
|
320
|
Chris@16
|
321
|
Chris@16
|
322 // This constructor supports multi_array's default constructor
|
Chris@16
|
323 // and constructors from multi_array_ref, subarray, and array_view
|
Chris@16
|
324 explicit
|
Chris@16
|
325 const_multi_array_ref(TPtr base,
|
Chris@16
|
326 const storage_order_type& so,
|
Chris@16
|
327 const index * index_bases,
|
Chris@16
|
328 const size_type* extents) :
|
Chris@16
|
329 base_(base), storage_(so), origin_offset_(0), directional_offset_(0)
|
Chris@16
|
330 {
|
Chris@16
|
331 // If index_bases or extents is null, then initialize the corresponding
|
Chris@16
|
332 // private data to zeroed lists.
|
Chris@16
|
333 if(index_bases) {
|
Chris@16
|
334 boost::detail::multi_array::
|
Chris@16
|
335 copy_n(index_bases,NumDims,index_base_list_.begin());
|
Chris@16
|
336 } else {
|
Chris@16
|
337 std::fill_n(index_base_list_.begin(),NumDims,0);
|
Chris@16
|
338 }
|
Chris@16
|
339 if(extents) {
|
Chris@16
|
340 init_multi_array_ref(extents);
|
Chris@16
|
341 } else {
|
Chris@16
|
342 boost::array<index,NumDims> extent_list;
|
Chris@16
|
343 extent_list.assign(0);
|
Chris@16
|
344 init_multi_array_ref(extent_list.begin());
|
Chris@16
|
345 }
|
Chris@16
|
346 }
|
Chris@16
|
347
|
Chris@16
|
348
|
Chris@16
|
349 TPtr base_;
|
Chris@16
|
350 storage_order_type storage_;
|
Chris@16
|
351 size_list extent_list_;
|
Chris@16
|
352 index_list stride_list_;
|
Chris@16
|
353 index_list index_base_list_;
|
Chris@16
|
354 index origin_offset_;
|
Chris@16
|
355 index directional_offset_;
|
Chris@16
|
356 size_type num_elements_;
|
Chris@16
|
357
|
Chris@16
|
358 private:
|
Chris@16
|
359 // const_multi_array_ref cannot be assigned to (no deep copies!)
|
Chris@16
|
360 const_multi_array_ref& operator=(const const_multi_array_ref& other);
|
Chris@16
|
361
|
Chris@16
|
362 void init_from_extent_gen(const
|
Chris@16
|
363 detail::multi_array::
|
Chris@16
|
364 extent_gen<NumDims>& ranges) {
|
Chris@16
|
365
|
Chris@16
|
366 typedef boost::array<index,NumDims> extent_list;
|
Chris@16
|
367
|
Chris@16
|
368 // get the index_base values
|
Chris@16
|
369 std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
|
Chris@16
|
370 index_base_list_.begin(),
|
Chris@16
|
371 boost::mem_fun_ref(&extent_range::start));
|
Chris@16
|
372
|
Chris@16
|
373 // calculate the extents
|
Chris@16
|
374 extent_list extents;
|
Chris@16
|
375 std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
|
Chris@16
|
376 extents.begin(),
|
Chris@16
|
377 boost::mem_fun_ref(&extent_range::size));
|
Chris@16
|
378
|
Chris@16
|
379 init_multi_array_ref(extents.begin());
|
Chris@16
|
380 }
|
Chris@16
|
381
|
Chris@16
|
382
|
Chris@16
|
383 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
Chris@16
|
384 protected:
|
Chris@16
|
385 #else
|
Chris@16
|
386 public:
|
Chris@16
|
387 #endif
|
Chris@16
|
388 // RG - move me!
|
Chris@16
|
389 template <class InputIterator>
|
Chris@16
|
390 void init_multi_array_ref(InputIterator extents_iter) {
|
Chris@16
|
391 boost::function_requires<InputIteratorConcept<InputIterator> >();
|
Chris@16
|
392
|
Chris@16
|
393 boost::detail::multi_array::
|
Chris@16
|
394 copy_n(extents_iter,num_dimensions(),extent_list_.begin());
|
Chris@16
|
395
|
Chris@16
|
396 // Calculate the array size
|
Chris@16
|
397 num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
|
Chris@16
|
398 size_type(1),std::multiplies<size_type>());
|
Chris@16
|
399
|
Chris@16
|
400 this->compute_strides(stride_list_,extent_list_,storage_);
|
Chris@16
|
401
|
Chris@16
|
402 origin_offset_ =
|
Chris@16
|
403 this->calculate_origin_offset(stride_list_,extent_list_,
|
Chris@16
|
404 storage_,index_base_list_);
|
Chris@16
|
405 directional_offset_ =
|
Chris@16
|
406 this->calculate_descending_dimension_offset(stride_list_,extent_list_,
|
Chris@16
|
407 storage_);
|
Chris@16
|
408 }
|
Chris@16
|
409 };
|
Chris@16
|
410
|
Chris@16
|
411 template <typename T, std::size_t NumDims>
|
Chris@16
|
412 class multi_array_ref :
|
Chris@16
|
413 public const_multi_array_ref<T,NumDims,T*>
|
Chris@16
|
414 {
|
Chris@16
|
415 typedef const_multi_array_ref<T,NumDims,T*> super_type;
|
Chris@16
|
416 public:
|
Chris@16
|
417 typedef typename super_type::value_type value_type;
|
Chris@16
|
418 typedef typename super_type::reference reference;
|
Chris@16
|
419 typedef typename super_type::iterator iterator;
|
Chris@16
|
420 typedef typename super_type::reverse_iterator reverse_iterator;
|
Chris@16
|
421 typedef typename super_type::const_reference const_reference;
|
Chris@16
|
422 typedef typename super_type::const_iterator const_iterator;
|
Chris@16
|
423 typedef typename super_type::const_reverse_iterator const_reverse_iterator;
|
Chris@16
|
424 typedef typename super_type::element element;
|
Chris@16
|
425 typedef typename super_type::size_type size_type;
|
Chris@16
|
426 typedef typename super_type::difference_type difference_type;
|
Chris@16
|
427 typedef typename super_type::index index;
|
Chris@16
|
428 typedef typename super_type::extent_range extent_range;
|
Chris@16
|
429
|
Chris@16
|
430 typedef typename super_type::storage_order_type storage_order_type;
|
Chris@16
|
431 typedef typename super_type::index_list index_list;
|
Chris@16
|
432 typedef typename super_type::size_list size_list;
|
Chris@16
|
433
|
Chris@16
|
434 template <std::size_t NDims>
|
Chris@16
|
435 struct const_array_view {
|
Chris@16
|
436 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
|
Chris@16
|
437 };
|
Chris@16
|
438
|
Chris@16
|
439 template <std::size_t NDims>
|
Chris@16
|
440 struct array_view {
|
Chris@16
|
441 typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
|
Chris@16
|
442 };
|
Chris@16
|
443
|
Chris@16
|
444 template <class ExtentList>
|
Chris@16
|
445 explicit multi_array_ref(T* base, const ExtentList& extents) :
|
Chris@16
|
446 super_type(base,extents) {
|
Chris@16
|
447 boost::function_requires<
|
Chris@16
|
448 CollectionConcept<ExtentList> >();
|
Chris@16
|
449 }
|
Chris@16
|
450
|
Chris@16
|
451 template <class ExtentList>
|
Chris@16
|
452 explicit multi_array_ref(T* base, const ExtentList& extents,
|
Chris@16
|
453 const general_storage_order<NumDims>& so) :
|
Chris@16
|
454 super_type(base,extents,so) {
|
Chris@16
|
455 boost::function_requires<
|
Chris@16
|
456 CollectionConcept<ExtentList> >();
|
Chris@16
|
457 }
|
Chris@16
|
458
|
Chris@16
|
459
|
Chris@16
|
460 explicit multi_array_ref(T* base,
|
Chris@16
|
461 const detail::multi_array::
|
Chris@16
|
462 extent_gen<NumDims>& ranges) :
|
Chris@16
|
463 super_type(base,ranges) { }
|
Chris@16
|
464
|
Chris@16
|
465
|
Chris@16
|
466 explicit multi_array_ref(T* base,
|
Chris@16
|
467 const detail::multi_array::
|
Chris@16
|
468 extent_gen<NumDims>&
|
Chris@16
|
469 ranges,
|
Chris@16
|
470 const general_storage_order<NumDims>& so) :
|
Chris@16
|
471 super_type(base,ranges,so) { }
|
Chris@16
|
472
|
Chris@16
|
473
|
Chris@16
|
474 // Assignment from other ConstMultiArray types.
|
Chris@16
|
475 template <typename ConstMultiArray>
|
Chris@16
|
476 multi_array_ref& operator=(const ConstMultiArray& other) {
|
Chris@16
|
477 function_requires<
|
Chris@16
|
478 multi_array_concepts::
|
Chris@16
|
479 ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
|
Chris@16
|
480
|
Chris@16
|
481 // make sure the dimensions agree
|
Chris@16
|
482 BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
|
Chris@16
|
483 BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(),
|
Chris@16
|
484 this->shape()));
|
Chris@16
|
485 // iterator-based copy
|
Chris@16
|
486 std::copy(other.begin(),other.end(),this->begin());
|
Chris@16
|
487 return *this;
|
Chris@16
|
488 }
|
Chris@16
|
489
|
Chris@16
|
490 multi_array_ref& operator=(const multi_array_ref& other) {
|
Chris@16
|
491 if (&other != this) {
|
Chris@16
|
492 // make sure the dimensions agree
|
Chris@16
|
493
|
Chris@16
|
494 BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
|
Chris@16
|
495 BOOST_ASSERT(std::equal(other.shape(),
|
Chris@16
|
496 other.shape()+this->num_dimensions(),
|
Chris@16
|
497 this->shape()));
|
Chris@16
|
498 // iterator-based copy
|
Chris@16
|
499 std::copy(other.begin(),other.end(),this->begin());
|
Chris@16
|
500 }
|
Chris@16
|
501 return *this;
|
Chris@16
|
502 }
|
Chris@16
|
503
|
Chris@16
|
504 element* origin() { return super_type::base_+super_type::origin_offset_; }
|
Chris@16
|
505
|
Chris@16
|
506 element* data() { return super_type::base_; }
|
Chris@16
|
507
|
Chris@16
|
508 template <class IndexList>
|
Chris@16
|
509 element& operator()(const IndexList& indices) {
|
Chris@16
|
510 boost::function_requires<
|
Chris@16
|
511 CollectionConcept<IndexList> >();
|
Chris@16
|
512 return super_type::access_element(boost::type<element&>(),
|
Chris@16
|
513 indices,origin(),
|
Chris@16
|
514 this->shape(),this->strides(),
|
Chris@16
|
515 this->index_bases());
|
Chris@16
|
516 }
|
Chris@16
|
517
|
Chris@16
|
518
|
Chris@16
|
519 reference operator[](index idx) {
|
Chris@16
|
520 return super_type::access(boost::type<reference>(),
|
Chris@16
|
521 idx,origin(),
|
Chris@16
|
522 this->shape(),this->strides(),
|
Chris@16
|
523 this->index_bases());
|
Chris@16
|
524 }
|
Chris@16
|
525
|
Chris@16
|
526
|
Chris@16
|
527 // See note attached to generate_array_view in base.hpp
|
Chris@16
|
528 template <int NDims>
|
Chris@16
|
529 typename array_view<NDims>::type
|
Chris@16
|
530 operator[](const detail::multi_array::
|
Chris@16
|
531 index_gen<NumDims,NDims>& indices) {
|
Chris@16
|
532 typedef typename array_view<NDims>::type return_type;
|
Chris@16
|
533 return
|
Chris@16
|
534 super_type::generate_array_view(boost::type<return_type>(),
|
Chris@16
|
535 indices,
|
Chris@16
|
536 this->shape(),
|
Chris@16
|
537 this->strides(),
|
Chris@16
|
538 this->index_bases(),
|
Chris@16
|
539 origin());
|
Chris@16
|
540 }
|
Chris@16
|
541
|
Chris@16
|
542
|
Chris@16
|
543 iterator begin() {
|
Chris@16
|
544 return iterator(*this->index_bases(),origin(),this->shape(),
|
Chris@16
|
545 this->strides(),this->index_bases());
|
Chris@16
|
546 }
|
Chris@16
|
547
|
Chris@16
|
548 iterator end() {
|
Chris@16
|
549 return iterator(*this->index_bases()+(index)*this->shape(),origin(),
|
Chris@16
|
550 this->shape(),this->strides(),
|
Chris@16
|
551 this->index_bases());
|
Chris@16
|
552 }
|
Chris@16
|
553
|
Chris@16
|
554 // rbegin() and rend() written naively to thwart MSVC ICE.
|
Chris@16
|
555 reverse_iterator rbegin() {
|
Chris@16
|
556 reverse_iterator ri(end());
|
Chris@16
|
557 return ri;
|
Chris@16
|
558 }
|
Chris@16
|
559
|
Chris@16
|
560 reverse_iterator rend() {
|
Chris@16
|
561 reverse_iterator ri(begin());
|
Chris@16
|
562 return ri;
|
Chris@16
|
563 }
|
Chris@16
|
564
|
Chris@16
|
565 // Using declarations don't seem to work for g++
|
Chris@16
|
566 // These are the proxies to work around this.
|
Chris@16
|
567
|
Chris@16
|
568 const element* origin() const { return super_type::origin(); }
|
Chris@16
|
569 const element* data() const { return super_type::data(); }
|
Chris@16
|
570
|
Chris@16
|
571 template <class IndexList>
|
Chris@16
|
572 const element& operator()(const IndexList& indices) const {
|
Chris@16
|
573 boost::function_requires<
|
Chris@16
|
574 CollectionConcept<IndexList> >();
|
Chris@16
|
575 return super_type::operator()(indices);
|
Chris@16
|
576 }
|
Chris@16
|
577
|
Chris@16
|
578 const_reference operator[](index idx) const {
|
Chris@16
|
579 return super_type::access(boost::type<const_reference>(),
|
Chris@16
|
580 idx,origin(),
|
Chris@16
|
581 this->shape(),this->strides(),
|
Chris@16
|
582 this->index_bases());
|
Chris@16
|
583 }
|
Chris@16
|
584
|
Chris@16
|
585 // See note attached to generate_array_view in base.hpp
|
Chris@16
|
586 template <int NDims>
|
Chris@16
|
587 typename const_array_view<NDims>::type
|
Chris@16
|
588 operator[](const detail::multi_array::
|
Chris@16
|
589 index_gen<NumDims,NDims>& indices)
|
Chris@16
|
590 const {
|
Chris@16
|
591 return super_type::operator[](indices);
|
Chris@16
|
592 }
|
Chris@16
|
593
|
Chris@16
|
594 const_iterator begin() const {
|
Chris@16
|
595 return super_type::begin();
|
Chris@16
|
596 }
|
Chris@16
|
597
|
Chris@16
|
598 const_iterator end() const {
|
Chris@16
|
599 return super_type::end();
|
Chris@16
|
600 }
|
Chris@16
|
601
|
Chris@16
|
602 const_reverse_iterator rbegin() const {
|
Chris@16
|
603 return super_type::rbegin();
|
Chris@16
|
604 }
|
Chris@16
|
605
|
Chris@16
|
606 const_reverse_iterator rend() const {
|
Chris@16
|
607 return super_type::rend();
|
Chris@16
|
608 }
|
Chris@16
|
609
|
Chris@16
|
610 protected:
|
Chris@16
|
611 // This is only supplied to support multi_array's default constructor
|
Chris@16
|
612 explicit multi_array_ref(T* base,
|
Chris@16
|
613 const storage_order_type& so,
|
Chris@16
|
614 const index* index_bases,
|
Chris@16
|
615 const size_type* extents) :
|
Chris@16
|
616 super_type(base,so,index_bases,extents) { }
|
Chris@16
|
617
|
Chris@16
|
618 };
|
Chris@16
|
619
|
Chris@16
|
620 } // namespace boost
|
Chris@16
|
621
|
Chris@16
|
622 #endif // BOOST_MULTI_ARRAY_REF_RG071801_HPP
|