Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/multi_array.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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_RG071801_HPP | |
14 #define BOOST_MULTI_ARRAY_RG071801_HPP | |
15 | |
16 // | |
17 // multi_array.hpp - contains the multi_array class template | |
18 // declaration and definition | |
19 // | |
20 | |
21 #include "boost/multi_array/base.hpp" | |
22 #include "boost/multi_array/collection_concept.hpp" | |
23 #include "boost/multi_array/copy_array.hpp" | |
24 #include "boost/multi_array/iterator.hpp" | |
25 #include "boost/multi_array/subarray.hpp" | |
26 #include "boost/multi_array/multi_array_ref.hpp" | |
27 #include "boost/multi_array/algorithm.hpp" | |
28 #include "boost/array.hpp" | |
29 #include "boost/mpl/if.hpp" | |
30 #include "boost/type_traits.hpp" | |
31 #include <algorithm> | |
32 #include <cstddef> | |
33 #include <functional> | |
34 #include <numeric> | |
35 #include <vector> | |
36 | |
37 | |
38 | |
39 namespace boost { | |
40 namespace detail { | |
41 namespace multi_array { | |
42 | |
43 struct populate_index_ranges { | |
44 multi_array_types::index_range | |
45 // RG: underscore on extent_ to stifle strange MSVC warning. | |
46 operator()(multi_array_types::index base, | |
47 multi_array_types::size_type extent_) { | |
48 return multi_array_types::index_range(base,base+extent_); | |
49 } | |
50 }; | |
51 | |
52 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING | |
53 // | |
54 // Compilers that don't support partial ordering may need help to | |
55 // disambiguate multi_array's templated constructors. Even vc6/7 are | |
56 // capable of some limited SFINAE, so we take the most-general version | |
57 // out of the overload set with disable_multi_array_impl. | |
58 // | |
59 template <typename T, std::size_t NumDims, typename TPtr> | |
60 char is_multi_array_impl_help(const_multi_array_view<T,NumDims,TPtr>&); | |
61 template <typename T, std::size_t NumDims, typename TPtr> | |
62 char is_multi_array_impl_help(const_sub_array<T,NumDims,TPtr>&); | |
63 template <typename T, std::size_t NumDims, typename TPtr> | |
64 char is_multi_array_impl_help(const_multi_array_ref<T,NumDims,TPtr>&); | |
65 | |
66 char ( &is_multi_array_impl_help(...) )[2]; | |
67 | |
68 template <class T> | |
69 struct is_multi_array_impl | |
70 { | |
71 static T x; | |
72 BOOST_STATIC_CONSTANT(bool, value = sizeof((is_multi_array_impl_help)(x)) == 1); | |
73 | |
74 typedef mpl::bool_<value> type; | |
75 }; | |
76 | |
77 template <bool multi_array = false> | |
78 struct disable_multi_array_impl_impl | |
79 { | |
80 typedef int type; | |
81 }; | |
82 | |
83 template <> | |
84 struct disable_multi_array_impl_impl<true> | |
85 { | |
86 // forming a pointer to a reference triggers SFINAE | |
87 typedef int& type; | |
88 }; | |
89 | |
90 | |
91 template <class T> | |
92 struct disable_multi_array_impl : | |
93 disable_multi_array_impl_impl<is_multi_array_impl<T>::value> | |
94 { }; | |
95 | |
96 | |
97 template <> | |
98 struct disable_multi_array_impl<int> | |
99 { | |
100 typedef int type; | |
101 }; | |
102 | |
103 | |
104 #endif | |
105 | |
106 } //namespace multi_array | |
107 } // namespace detail | |
108 | |
109 template<typename T, std::size_t NumDims, | |
110 typename Allocator> | |
111 class multi_array : | |
112 public multi_array_ref<T,NumDims> | |
113 { | |
114 typedef multi_array_ref<T,NumDims> super_type; | |
115 public: | |
116 typedef typename super_type::value_type value_type; | |
117 typedef typename super_type::reference reference; | |
118 typedef typename super_type::const_reference const_reference; | |
119 typedef typename super_type::iterator iterator; | |
120 typedef typename super_type::const_iterator const_iterator; | |
121 typedef typename super_type::reverse_iterator reverse_iterator; | |
122 typedef typename super_type::const_reverse_iterator const_reverse_iterator; | |
123 typedef typename super_type::element element; | |
124 typedef typename super_type::size_type size_type; | |
125 typedef typename super_type::difference_type difference_type; | |
126 typedef typename super_type::index index; | |
127 typedef typename super_type::extent_range extent_range; | |
128 | |
129 | |
130 template <std::size_t NDims> | |
131 struct const_array_view { | |
132 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type; | |
133 }; | |
134 | |
135 template <std::size_t NDims> | |
136 struct array_view { | |
137 typedef boost::detail::multi_array::multi_array_view<T,NDims> type; | |
138 }; | |
139 | |
140 explicit multi_array() : | |
141 super_type((T*)initial_base_,c_storage_order(), | |
142 /*index_bases=*/0, /*extents=*/0) { | |
143 allocate_space(); | |
144 } | |
145 | |
146 template <class ExtentList> | |
147 explicit multi_array( | |
148 ExtentList const& extents | |
149 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING | |
150 , typename mpl::if_< | |
151 detail::multi_array::is_multi_array_impl<ExtentList>, | |
152 int&,int>::type* = 0 | |
153 #endif | |
154 ) : | |
155 super_type((T*)initial_base_,extents) { | |
156 boost::function_requires< | |
157 detail::multi_array::CollectionConcept<ExtentList> >(); | |
158 allocate_space(); | |
159 } | |
160 | |
161 | |
162 template <class ExtentList> | |
163 explicit multi_array(ExtentList const& extents, | |
164 const general_storage_order<NumDims>& so) : | |
165 super_type((T*)initial_base_,extents,so) { | |
166 boost::function_requires< | |
167 detail::multi_array::CollectionConcept<ExtentList> >(); | |
168 allocate_space(); | |
169 } | |
170 | |
171 template <class ExtentList> | |
172 explicit multi_array(ExtentList const& extents, | |
173 const general_storage_order<NumDims>& so, | |
174 Allocator const& alloc) : | |
175 super_type((T*)initial_base_,extents,so), allocator_(alloc) { | |
176 boost::function_requires< | |
177 detail::multi_array::CollectionConcept<ExtentList> >(); | |
178 allocate_space(); | |
179 } | |
180 | |
181 | |
182 explicit multi_array(const detail::multi_array | |
183 ::extent_gen<NumDims>& ranges) : | |
184 super_type((T*)initial_base_,ranges) { | |
185 | |
186 allocate_space(); | |
187 } | |
188 | |
189 | |
190 explicit multi_array(const detail::multi_array | |
191 ::extent_gen<NumDims>& ranges, | |
192 const general_storage_order<NumDims>& so) : | |
193 super_type((T*)initial_base_,ranges,so) { | |
194 | |
195 allocate_space(); | |
196 } | |
197 | |
198 | |
199 explicit multi_array(const detail::multi_array | |
200 ::extent_gen<NumDims>& ranges, | |
201 const general_storage_order<NumDims>& so, | |
202 Allocator const& alloc) : | |
203 super_type((T*)initial_base_,ranges,so), allocator_(alloc) { | |
204 | |
205 allocate_space(); | |
206 } | |
207 | |
208 multi_array(const multi_array& rhs) : | |
209 super_type(rhs), allocator_(rhs.allocator_) { | |
210 allocate_space(); | |
211 boost::detail::multi_array::copy_n(rhs.base_,rhs.num_elements(),base_); | |
212 } | |
213 | |
214 | |
215 // | |
216 // A multi_array is constructible from any multi_array_ref, subarray, or | |
217 // array_view object. The following constructors ensure that. | |
218 // | |
219 | |
220 // Due to limited support for partial template ordering, | |
221 // MSVC 6&7 confuse the following with the most basic ExtentList | |
222 // constructor. | |
223 #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING | |
224 template <typename OPtr> | |
225 multi_array(const const_multi_array_ref<T,NumDims,OPtr>& rhs, | |
226 const general_storage_order<NumDims>& so = c_storage_order()) | |
227 : super_type(0,so,rhs.index_bases(),rhs.shape()) | |
228 { | |
229 allocate_space(); | |
230 // Warning! storage order may change, hence the following copy technique. | |
231 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
232 } | |
233 | |
234 template <typename OPtr> | |
235 multi_array(const detail::multi_array:: | |
236 const_sub_array<T,NumDims,OPtr>& rhs, | |
237 const general_storage_order<NumDims>& so = c_storage_order()) | |
238 : super_type(0,so,rhs.index_bases(),rhs.shape()) | |
239 { | |
240 allocate_space(); | |
241 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
242 } | |
243 | |
244 | |
245 template <typename OPtr> | |
246 multi_array(const detail::multi_array:: | |
247 const_multi_array_view<T,NumDims,OPtr>& rhs, | |
248 const general_storage_order<NumDims>& so = c_storage_order()) | |
249 : super_type(0,so,rhs.index_bases(),rhs.shape()) | |
250 { | |
251 allocate_space(); | |
252 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
253 } | |
254 | |
255 #else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING | |
256 // More limited support for MSVC | |
257 | |
258 | |
259 multi_array(const const_multi_array_ref<T,NumDims>& rhs) | |
260 : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) | |
261 { | |
262 allocate_space(); | |
263 // Warning! storage order may change, hence the following copy technique. | |
264 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
265 } | |
266 | |
267 multi_array(const const_multi_array_ref<T,NumDims>& rhs, | |
268 const general_storage_order<NumDims>& so) | |
269 : super_type(0,so,rhs.index_bases(),rhs.shape()) | |
270 { | |
271 allocate_space(); | |
272 // Warning! storage order may change, hence the following copy technique. | |
273 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
274 } | |
275 | |
276 multi_array(const detail::multi_array:: | |
277 const_sub_array<T,NumDims>& rhs) | |
278 : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) | |
279 { | |
280 allocate_space(); | |
281 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
282 } | |
283 | |
284 multi_array(const detail::multi_array:: | |
285 const_sub_array<T,NumDims>& rhs, | |
286 const general_storage_order<NumDims>& so) | |
287 : super_type(0,so,rhs.index_bases(),rhs.shape()) | |
288 { | |
289 allocate_space(); | |
290 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
291 } | |
292 | |
293 | |
294 multi_array(const detail::multi_array:: | |
295 const_multi_array_view<T,NumDims>& rhs) | |
296 : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) | |
297 { | |
298 allocate_space(); | |
299 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
300 } | |
301 | |
302 multi_array(const detail::multi_array:: | |
303 const_multi_array_view<T,NumDims>& rhs, | |
304 const general_storage_order<NumDims>& so) | |
305 : super_type(0,so,rhs.index_bases(),rhs.shape()) | |
306 { | |
307 allocate_space(); | |
308 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
309 } | |
310 | |
311 #endif // !BOOST_NO_FUNCTION_TEMPLATE_ORDERING | |
312 | |
313 // Thes constructors are necessary because of more exact template matches. | |
314 multi_array(const multi_array_ref<T,NumDims>& rhs) | |
315 : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) | |
316 { | |
317 allocate_space(); | |
318 // Warning! storage order may change, hence the following copy technique. | |
319 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
320 } | |
321 | |
322 multi_array(const multi_array_ref<T,NumDims>& rhs, | |
323 const general_storage_order<NumDims>& so) | |
324 : super_type(0,so,rhs.index_bases(),rhs.shape()) | |
325 { | |
326 allocate_space(); | |
327 // Warning! storage order may change, hence the following copy technique. | |
328 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
329 } | |
330 | |
331 | |
332 multi_array(const detail::multi_array:: | |
333 sub_array<T,NumDims>& rhs) | |
334 : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) | |
335 { | |
336 allocate_space(); | |
337 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
338 } | |
339 | |
340 multi_array(const detail::multi_array:: | |
341 sub_array<T,NumDims>& rhs, | |
342 const general_storage_order<NumDims>& so) | |
343 : super_type(0,so,rhs.index_bases(),rhs.shape()) | |
344 { | |
345 allocate_space(); | |
346 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
347 } | |
348 | |
349 | |
350 multi_array(const detail::multi_array:: | |
351 multi_array_view<T,NumDims>& rhs) | |
352 : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()) | |
353 { | |
354 allocate_space(); | |
355 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
356 } | |
357 | |
358 multi_array(const detail::multi_array:: | |
359 multi_array_view<T,NumDims>& rhs, | |
360 const general_storage_order<NumDims>& so) | |
361 : super_type(0,so,rhs.index_bases(),rhs.shape()) | |
362 { | |
363 allocate_space(); | |
364 std::copy(rhs.begin(),rhs.end(),this->begin()); | |
365 } | |
366 | |
367 // Since assignment is a deep copy, multi_array_ref | |
368 // contains all the necessary code. | |
369 template <typename ConstMultiArray> | |
370 multi_array& operator=(const ConstMultiArray& other) { | |
371 super_type::operator=(other); | |
372 return *this; | |
373 } | |
374 | |
375 multi_array& operator=(const multi_array& other) { | |
376 if (&other != this) { | |
377 super_type::operator=(other); | |
378 } | |
379 return *this; | |
380 } | |
381 | |
382 | |
383 template <typename ExtentList> | |
384 multi_array& resize(const ExtentList& extents) { | |
385 boost::function_requires< | |
386 detail::multi_array::CollectionConcept<ExtentList> >(); | |
387 | |
388 typedef detail::multi_array::extent_gen<NumDims> gen_type; | |
389 gen_type ranges; | |
390 | |
391 for (int i=0; i != NumDims; ++i) { | |
392 typedef typename gen_type::range range_type; | |
393 ranges.ranges_[i] = range_type(0,extents[i]); | |
394 } | |
395 | |
396 return this->resize(ranges); | |
397 } | |
398 | |
399 | |
400 | |
401 multi_array& resize(const detail::multi_array | |
402 ::extent_gen<NumDims>& ranges) { | |
403 | |
404 | |
405 // build a multi_array with the specs given | |
406 multi_array new_array(ranges,this->storage_order()); | |
407 | |
408 | |
409 // build a view of tmp with the minimum extents | |
410 | |
411 // Get the minimum extents of the arrays. | |
412 boost::array<size_type,NumDims> min_extents; | |
413 | |
414 const size_type& (*min)(const size_type&, const size_type&) = | |
415 std::min; | |
416 std::transform(new_array.extent_list_.begin(),new_array.extent_list_.end(), | |
417 this->extent_list_.begin(), | |
418 min_extents.begin(), | |
419 min); | |
420 | |
421 | |
422 // typedef boost::array<index,NumDims> index_list; | |
423 // Build index_gen objects to create views with the same shape | |
424 | |
425 // these need to be separate to handle non-zero index bases | |
426 typedef detail::multi_array::index_gen<NumDims,NumDims> index_gen; | |
427 index_gen old_idxes; | |
428 index_gen new_idxes; | |
429 | |
430 std::transform(new_array.index_base_list_.begin(), | |
431 new_array.index_base_list_.end(), | |
432 min_extents.begin(),new_idxes.ranges_.begin(), | |
433 detail::multi_array::populate_index_ranges()); | |
434 | |
435 std::transform(this->index_base_list_.begin(), | |
436 this->index_base_list_.end(), | |
437 min_extents.begin(),old_idxes.ranges_.begin(), | |
438 detail::multi_array::populate_index_ranges()); | |
439 | |
440 // Build same-shape views of the two arrays | |
441 typename | |
442 multi_array::BOOST_NESTED_TEMPLATE array_view<NumDims>::type view_old = (*this)[old_idxes]; | |
443 typename | |
444 multi_array::BOOST_NESTED_TEMPLATE array_view<NumDims>::type view_new = new_array[new_idxes]; | |
445 | |
446 // Set the right portion of the new array | |
447 view_new = view_old; | |
448 | |
449 using std::swap; | |
450 // Swap the internals of these arrays. | |
451 swap(this->super_type::base_,new_array.super_type::base_); | |
452 swap(this->storage_,new_array.storage_); | |
453 swap(this->extent_list_,new_array.extent_list_); | |
454 swap(this->stride_list_,new_array.stride_list_); | |
455 swap(this->index_base_list_,new_array.index_base_list_); | |
456 swap(this->origin_offset_,new_array.origin_offset_); | |
457 swap(this->directional_offset_,new_array.directional_offset_); | |
458 swap(this->num_elements_,new_array.num_elements_); | |
459 swap(this->allocator_,new_array.allocator_); | |
460 swap(this->base_,new_array.base_); | |
461 swap(this->allocated_elements_,new_array.allocated_elements_); | |
462 | |
463 return *this; | |
464 } | |
465 | |
466 | |
467 ~multi_array() { | |
468 deallocate_space(); | |
469 } | |
470 | |
471 private: | |
472 void allocate_space() { | |
473 typename Allocator::const_pointer no_hint=0; | |
474 base_ = allocator_.allocate(this->num_elements(),no_hint); | |
475 this->set_base_ptr(base_); | |
476 allocated_elements_ = this->num_elements(); | |
477 std::uninitialized_fill_n(base_,allocated_elements_,T()); | |
478 } | |
479 | |
480 void deallocate_space() { | |
481 if(base_) { | |
482 for(T* i = base_; i != base_+allocated_elements_; ++i) | |
483 allocator_.destroy(i); | |
484 allocator_.deallocate(base_,allocated_elements_); | |
485 } | |
486 } | |
487 | |
488 typedef boost::array<size_type,NumDims> size_list; | |
489 typedef boost::array<index,NumDims> index_list; | |
490 | |
491 Allocator allocator_; | |
492 T* base_; | |
493 size_type allocated_elements_; | |
494 enum {initial_base_ = 0}; | |
495 }; | |
496 | |
497 } // namespace boost | |
498 | |
499 #endif // BOOST_MULTI_ARRAY_RG071801_HPP |