PageRenderTime 58ms CodeModel.GetById 19ms app.highlight 35ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/multi_array.hpp

http://hadesmem.googlecode.com/
C++ Header | 499 lines | 355 code | 98 blank | 46 comment | 8 complexity | a6283b441562b017719b7cb40a559154 MD5 | raw file
  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
 39namespace 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//
 59template <typename T, std::size_t NumDims, typename TPtr>
 60char is_multi_array_impl_help(const_multi_array_view<T,NumDims,TPtr>&);
 61template <typename T, std::size_t NumDims, typename TPtr>
 62char is_multi_array_impl_help(const_sub_array<T,NumDims,TPtr>&);
 63template <typename T, std::size_t NumDims, typename TPtr>
 64char is_multi_array_impl_help(const_multi_array_ref<T,NumDims,TPtr>&);
 65
 66char ( &is_multi_array_impl_help(...) )[2];
 67
 68template <class T>
 69struct 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
 77template <bool multi_array = false>
 78struct disable_multi_array_impl_impl
 79{
 80    typedef int type;
 81};
 82
 83template <>
 84struct disable_multi_array_impl_impl<true>
 85{
 86    // forming a pointer to a reference triggers SFINAE
 87    typedef int& type; 
 88};
 89
 90
 91template <class T>
 92struct disable_multi_array_impl :
 93  disable_multi_array_impl_impl<is_multi_array_impl<T>::value>
 94{ };
 95
 96
 97template <>
 98struct disable_multi_array_impl<int>
 99{
100  typedef int type;
101};
102
103
104#endif
105
106    } //namespace multi_array
107  } // namespace detail
108
109template<typename T, std::size_t NumDims,
110  typename Allocator>
111class multi_array :
112  public multi_array_ref<T,NumDims>
113{
114  typedef multi_array_ref<T,NumDims> super_type;
115public:
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
471private:
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