ossrv_pub/boost_apis/boost/multi_array.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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(),old_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(),new_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