Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/multi_array.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright 2002 The Trustees of Indiana University.
0002 
0003 // Copyright 2018 Glen Joseph Fernandes
0004 // (glenjofe@gmail.com)
0005 
0006 // Use, modification and distribution is subject to the Boost Software 
0007 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0008 // http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 //  Boost.MultiArray Library
0011 //  Authors: Ronald Garcia
0012 //           Jeremy Siek
0013 //           Andrew Lumsdaine
0014 //  See http://www.boost.org/libs/multi_array for documentation.
0015 
0016 #ifndef BOOST_MULTI_ARRAY_HPP
0017 #define BOOST_MULTI_ARRAY_HPP
0018 
0019 //
0020 // multi_array.hpp - contains the multi_array class template
0021 // declaration and definition
0022 //
0023 
0024 #if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 406)
0025 #  pragma GCC diagnostic push
0026 #  pragma GCC diagnostic ignored "-Wshadow"
0027 #endif
0028 
0029 #include "boost/multi_array/base.hpp"
0030 #include "boost/multi_array/collection_concept.hpp"
0031 #include "boost/multi_array/copy_array.hpp"
0032 #include "boost/multi_array/iterator.hpp"
0033 #include "boost/multi_array/subarray.hpp"
0034 #include "boost/multi_array/multi_array_ref.hpp"
0035 #include "boost/multi_array/algorithm.hpp"
0036 #include "boost/core/alloc_construct.hpp"
0037 #include "boost/core/empty_value.hpp"
0038 #include "boost/array.hpp"
0039 #include "boost/mpl/if.hpp"
0040 #include "boost/type_traits.hpp"
0041 #include <algorithm>
0042 #include <cstddef>
0043 #include <functional>
0044 #include <numeric>
0045 #include <vector>
0046 
0047 
0048 
0049 namespace boost {
0050   namespace detail {
0051     namespace multi_array {
0052 
0053       struct populate_index_ranges {
0054         multi_array_types::index_range
0055         // RG: underscore on extent_ to stifle strange MSVC warning.
0056         operator()(multi_array_types::index base,
0057                    multi_array_types::size_type extent_) {
0058           return multi_array_types::index_range(base,base+extent_);
0059         }
0060       };
0061 
0062 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
0063 //
0064 // Compilers that don't support partial ordering may need help to
0065 // disambiguate multi_array's templated constructors.  Even vc6/7 are
0066 // capable of some limited SFINAE, so we take the most-general version
0067 // out of the overload set with disable_multi_array_impl.
0068 //
0069 template <typename T, std::size_t NumDims, typename TPtr>
0070 char is_multi_array_impl_help(const_multi_array_view<T,NumDims,TPtr>&);
0071 template <typename T, std::size_t NumDims, typename TPtr>
0072 char is_multi_array_impl_help(const_sub_array<T,NumDims,TPtr>&);
0073 template <typename T, std::size_t NumDims, typename TPtr>
0074 char is_multi_array_impl_help(const_multi_array_ref<T,NumDims,TPtr>&);
0075 
0076 char ( &is_multi_array_impl_help(...) )[2];
0077 
0078 template <class T>
0079 struct is_multi_array_impl
0080 {
0081     static T x;
0082     BOOST_STATIC_CONSTANT(bool, value = sizeof((is_multi_array_impl_help)(x)) == 1);
0083 
0084   typedef mpl::bool_<value> type;
0085 };
0086 
0087 template <bool multi_array = false>
0088 struct disable_multi_array_impl_impl
0089 {
0090     typedef int type;
0091 };
0092 
0093 template <>
0094 struct disable_multi_array_impl_impl<true>
0095 {
0096     // forming a pointer to a reference triggers SFINAE
0097     typedef int& type; 
0098 };
0099 
0100 
0101 template <class T>
0102 struct disable_multi_array_impl :
0103   disable_multi_array_impl_impl<is_multi_array_impl<T>::value>
0104 { };
0105 
0106 
0107 template <>
0108 struct disable_multi_array_impl<int>
0109 {
0110   typedef int type;
0111 };
0112 
0113 
0114 #endif
0115 
0116     } //namespace multi_array
0117   } // namespace detail
0118 
0119 template<typename T, std::size_t NumDims,
0120   typename Allocator>
0121 class multi_array :
0122   public multi_array_ref<T,NumDims>,
0123   private boost::empty_value<Allocator>
0124 {
0125   typedef boost::empty_value<Allocator> alloc_base;
0126   typedef multi_array_ref<T,NumDims> super_type;
0127 public:
0128   typedef typename super_type::value_type value_type;
0129   typedef typename super_type::reference reference;
0130   typedef typename super_type::const_reference const_reference;
0131   typedef typename super_type::iterator iterator;
0132   typedef typename super_type::const_iterator const_iterator;
0133   typedef typename super_type::reverse_iterator reverse_iterator;
0134   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
0135   typedef typename super_type::element element;
0136   typedef typename super_type::size_type size_type;
0137   typedef typename super_type::difference_type difference_type;
0138   typedef typename super_type::index index;
0139   typedef typename super_type::extent_range extent_range;
0140 
0141 
0142   template <std::size_t NDims>
0143   struct const_array_view {
0144     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
0145   };
0146 
0147   template <std::size_t NDims>
0148   struct array_view {
0149     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
0150   };
0151 
0152   explicit multi_array(const Allocator& alloc = Allocator()) :
0153     super_type((T*)initial_base_,c_storage_order(),
0154                /*index_bases=*/0, /*extents=*/0),
0155     alloc_base(boost::empty_init_t(),alloc) {
0156     allocate_space(); 
0157   }
0158 
0159   template <class ExtentList>
0160   explicit multi_array(
0161       ExtentList const& extents,
0162       const Allocator& alloc = Allocator()
0163 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
0164       , typename mpl::if_<
0165       detail::multi_array::is_multi_array_impl<ExtentList>,
0166       int&,int>::type* = 0
0167 #endif
0168       ) :
0169     super_type((T*)initial_base_,extents),
0170     alloc_base(boost::empty_init_t(),alloc) {
0171     boost::function_requires<
0172       detail::multi_array::CollectionConcept<ExtentList> >();
0173     allocate_space();
0174   }
0175 
0176     
0177   template <class ExtentList>
0178   explicit multi_array(ExtentList const& extents,
0179                        const general_storage_order<NumDims>& so) :
0180     super_type((T*)initial_base_,extents,so),
0181     alloc_base(boost::empty_init_t()) {
0182     boost::function_requires<
0183       detail::multi_array::CollectionConcept<ExtentList> >();
0184     allocate_space();
0185   }
0186 
0187   template <class ExtentList>
0188   explicit multi_array(ExtentList const& extents,
0189                        const general_storage_order<NumDims>& so,
0190                        Allocator const& alloc) :
0191     super_type((T*)initial_base_,extents,so),
0192     alloc_base(boost::empty_init_t(),alloc) {
0193     boost::function_requires<
0194       detail::multi_array::CollectionConcept<ExtentList> >();
0195     allocate_space();
0196   }
0197 
0198 
0199   explicit multi_array(const detail::multi_array
0200                        ::extent_gen<NumDims>& ranges,
0201                        const Allocator& alloc = Allocator()) :
0202     super_type((T*)initial_base_,ranges),
0203     alloc_base(boost::empty_init_t(),alloc) {
0204 
0205     allocate_space();
0206   }
0207 
0208 
0209   explicit multi_array(const detail::multi_array
0210                        ::extent_gen<NumDims>& ranges,
0211                        const general_storage_order<NumDims>& so) :
0212     super_type((T*)initial_base_,ranges,so),
0213     alloc_base(boost::empty_init_t()) {
0214 
0215     allocate_space();
0216   }
0217 
0218 
0219   explicit multi_array(const detail::multi_array
0220                        ::extent_gen<NumDims>& ranges,
0221                        const general_storage_order<NumDims>& so,
0222                        Allocator const& alloc) :
0223     super_type((T*)initial_base_,ranges,so),
0224     alloc_base(boost::empty_init_t(),alloc) {
0225 
0226     allocate_space();
0227   }
0228 
0229   multi_array(const multi_array& rhs) :
0230   super_type(rhs),
0231   alloc_base(static_cast<const alloc_base&>(rhs)) {
0232     allocate_space();
0233     boost::detail::multi_array::copy_n(rhs.base_,rhs.num_elements(),base_);
0234   }
0235 
0236 
0237   //
0238   // A multi_array is constructible from any multi_array_ref, subarray, or
0239   // array_view object.  The following constructors ensure that.
0240   //
0241 
0242   // Due to limited support for partial template ordering, 
0243   // MSVC 6&7 confuse the following with the most basic ExtentList 
0244   // constructor.
0245 #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
0246   template <typename OPtr>
0247   multi_array(const const_multi_array_ref<T,NumDims,OPtr>& rhs,
0248               const general_storage_order<NumDims>& so = c_storage_order(),
0249               const Allocator& alloc = Allocator())
0250     : super_type(0,so,rhs.index_bases(),rhs.shape()),
0251       alloc_base(boost::empty_init_t(),alloc)
0252   {
0253     allocate_space();
0254     // Warning! storage order may change, hence the following copy technique.
0255     std::copy(rhs.begin(),rhs.end(),this->begin());
0256   }
0257 
0258   template <typename OPtr>
0259   multi_array(const detail::multi_array::
0260               const_sub_array<T,NumDims,OPtr>& rhs,
0261               const general_storage_order<NumDims>& so = c_storage_order(),
0262               const Allocator& alloc = Allocator())
0263     : super_type(0,so,rhs.index_bases(),rhs.shape()),
0264       alloc_base(boost::empty_init_t(),alloc)
0265   {
0266     allocate_space();
0267     std::copy(rhs.begin(),rhs.end(),this->begin());
0268   }
0269 
0270 
0271   template <typename OPtr>
0272   multi_array(const detail::multi_array::
0273               const_multi_array_view<T,NumDims,OPtr>& rhs,
0274               const general_storage_order<NumDims>& so = c_storage_order(),
0275               const Allocator& alloc = Allocator())
0276     : super_type(0,so,rhs.index_bases(),rhs.shape()),
0277       alloc_base(boost::empty_init_t(),alloc)
0278   {
0279     allocate_space();
0280     std::copy(rhs.begin(),rhs.end(),this->begin());
0281   }
0282 
0283 #else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
0284   // More limited support for MSVC
0285 
0286 
0287   multi_array(const const_multi_array_ref<T,NumDims>& rhs,
0288               const Allocator& alloc = Allocator())
0289     : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()),
0290       alloc_base(boost::empty_init_t(),alloc)
0291   {
0292     allocate_space();
0293     // Warning! storage order may change, hence the following copy technique.
0294     std::copy(rhs.begin(),rhs.end(),this->begin());
0295   }
0296 
0297   multi_array(const const_multi_array_ref<T,NumDims>& rhs,
0298               const general_storage_order<NumDims>& so,
0299               const Allocator& alloc = Allocator())
0300     : super_type(0,so,rhs.index_bases(),rhs.shape()),
0301       alloc_base(boost::empty_init_t(),alloc)
0302   {
0303     allocate_space();
0304     // Warning! storage order may change, hence the following copy technique.
0305     std::copy(rhs.begin(),rhs.end(),this->begin());
0306   }
0307 
0308   multi_array(const detail::multi_array::
0309               const_sub_array<T,NumDims>& rhs,
0310               const Allocator& alloc = Allocator())
0311     : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()),
0312       alloc_base(boost::empty_init_t(),alloc)
0313   {
0314     allocate_space();
0315     std::copy(rhs.begin(),rhs.end(),this->begin());
0316   }
0317 
0318   multi_array(const detail::multi_array::
0319               const_sub_array<T,NumDims>& rhs,
0320               const general_storage_order<NumDims>& so,
0321               const Allocator& alloc = Allocator())
0322     : super_type(0,so,rhs.index_bases(),rhs.shape()),
0323       alloc_base(boost::empty_init_t(),alloc)
0324   {
0325     allocate_space();
0326     std::copy(rhs.begin(),rhs.end(),this->begin());
0327   }
0328 
0329 
0330   multi_array(const detail::multi_array::
0331               const_multi_array_view<T,NumDims>& rhs,
0332               const Allocator& alloc = Allocator())
0333     : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()),
0334       alloc_base(boost::empty_init_t(),alloc)
0335   {
0336     allocate_space();
0337     std::copy(rhs.begin(),rhs.end(),this->begin());
0338   }
0339 
0340   multi_array(const detail::multi_array::
0341               const_multi_array_view<T,NumDims>& rhs,
0342               const general_storage_order<NumDims>& so,
0343               const Allocator& alloc = Allocator())
0344     : super_type(0,so,rhs.index_bases(),rhs.shape()),
0345       alloc_base(boost::empty_init_t(),alloc)
0346   {
0347     allocate_space();
0348     std::copy(rhs.begin(),rhs.end(),this->begin());
0349   }
0350 
0351 #endif // !BOOST_NO_FUNCTION_TEMPLATE_ORDERING
0352 
0353   // Thes constructors are necessary because of more exact template matches.
0354   multi_array(const multi_array_ref<T,NumDims>& rhs,
0355               const Allocator& alloc = Allocator())
0356     : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()),
0357       alloc_base(boost::empty_init_t(),alloc)
0358   {
0359     allocate_space();
0360     // Warning! storage order may change, hence the following copy technique.
0361     std::copy(rhs.begin(),rhs.end(),this->begin());
0362   }
0363 
0364   multi_array(const multi_array_ref<T,NumDims>& rhs,
0365               const general_storage_order<NumDims>& so,
0366               const Allocator& alloc = Allocator())
0367     : super_type(0,so,rhs.index_bases(),rhs.shape()),
0368       alloc_base(boost::empty_init_t(),alloc)
0369   {
0370     allocate_space();
0371     // Warning! storage order may change, hence the following copy technique.
0372     std::copy(rhs.begin(),rhs.end(),this->begin());
0373   }
0374 
0375 
0376   multi_array(const detail::multi_array::
0377               sub_array<T,NumDims>& rhs,
0378               const Allocator& alloc = Allocator())
0379     : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()),
0380       alloc_base(boost::empty_init_t(),alloc)
0381   {
0382     allocate_space();
0383     std::copy(rhs.begin(),rhs.end(),this->begin());
0384   }
0385 
0386   multi_array(const detail::multi_array::
0387               sub_array<T,NumDims>& rhs,
0388               const general_storage_order<NumDims>& so,
0389               const Allocator& alloc = Allocator())
0390     : super_type(0,so,rhs.index_bases(),rhs.shape()),
0391       alloc_base(boost::empty_init_t(),alloc)
0392   {
0393     allocate_space();
0394     std::copy(rhs.begin(),rhs.end(),this->begin());
0395   }
0396 
0397 
0398   multi_array(const detail::multi_array::
0399               multi_array_view<T,NumDims>& rhs,
0400               const Allocator& alloc = Allocator())
0401     : super_type(0,c_storage_order(),rhs.index_bases(),rhs.shape()),
0402       alloc_base(boost::empty_init_t(),alloc)
0403   {
0404     allocate_space();
0405     std::copy(rhs.begin(),rhs.end(),this->begin());
0406   }
0407     
0408   multi_array(const detail::multi_array::
0409               multi_array_view<T,NumDims>& rhs,
0410               const general_storage_order<NumDims>& so,
0411               const Allocator& alloc = Allocator())
0412     : super_type(0,so,rhs.index_bases(),rhs.shape()),
0413       alloc_base(boost::empty_init_t(),alloc)
0414   {
0415     allocate_space();
0416     std::copy(rhs.begin(),rhs.end(),this->begin());
0417   }
0418     
0419   // Since assignment is a deep copy, multi_array_ref
0420   // contains all the necessary code.
0421   template <typename ConstMultiArray>
0422   multi_array& operator=(const ConstMultiArray& other) {
0423     super_type::operator=(other);
0424     return *this;
0425   }
0426 
0427   multi_array& operator=(const multi_array& other) {
0428     if (&other != this) {
0429       super_type::operator=(other);
0430     }
0431     return *this;
0432   }
0433 
0434 
0435   template <typename ExtentList>
0436   multi_array& resize(const ExtentList& extents) {
0437     boost::function_requires<
0438       detail::multi_array::CollectionConcept<ExtentList> >();
0439 
0440     typedef detail::multi_array::extent_gen<NumDims> gen_type;
0441     gen_type ranges;
0442 
0443     for (int i=0; i != NumDims; ++i) {
0444       typedef typename gen_type::range range_type;
0445       ranges.ranges_[i] = range_type(0,extents[i]);
0446     }
0447     
0448     return this->resize(ranges);
0449   }
0450 
0451 
0452 
0453   multi_array& resize(const detail::multi_array
0454                       ::extent_gen<NumDims>& ranges) {
0455 
0456 
0457     // build a multi_array with the specs given
0458     multi_array new_array(ranges,this->storage_order(),allocator());
0459 
0460 
0461     // build a view of tmp with the minimum extents
0462 
0463     // Get the minimum extents of the arrays.
0464     boost::array<size_type,NumDims> min_extents;
0465 
0466     const size_type& (*min)(const size_type&, const size_type&) =
0467       std::min;
0468     std::transform(new_array.extent_list_.begin(),new_array.extent_list_.end(),
0469                    this->extent_list_.begin(),
0470                    min_extents.begin(),
0471                    min);
0472 
0473 
0474     // typedef boost::array<index,NumDims> index_list;
0475     // Build index_gen objects to create views with the same shape
0476 
0477     // these need to be separate to handle non-zero index bases
0478     typedef detail::multi_array::index_gen<NumDims,NumDims> index_gen;
0479     index_gen old_idxes;
0480     index_gen new_idxes;
0481 
0482     std::transform(new_array.index_base_list_.begin(),
0483                    new_array.index_base_list_.end(),
0484                    min_extents.begin(),new_idxes.ranges_.begin(),
0485                    detail::multi_array::populate_index_ranges());
0486 
0487     std::transform(this->index_base_list_.begin(),
0488                    this->index_base_list_.end(),
0489                    min_extents.begin(),old_idxes.ranges_.begin(),
0490                    detail::multi_array::populate_index_ranges());
0491 
0492     // Build same-shape views of the two arrays
0493     typename
0494       multi_array::BOOST_NESTED_TEMPLATE array_view<NumDims>::type view_old = (*this)[old_idxes];
0495     typename
0496       multi_array::BOOST_NESTED_TEMPLATE array_view<NumDims>::type view_new = new_array[new_idxes];
0497 
0498     // Set the right portion of the new array
0499     view_new = view_old;
0500 
0501     using std::swap;
0502     // Swap the internals of these arrays.
0503     swap(this->super_type::base_,new_array.super_type::base_);
0504     swap(this->allocator(),new_array.allocator());
0505     swap(this->storage_,new_array.storage_);
0506     swap(this->extent_list_,new_array.extent_list_);
0507     swap(this->stride_list_,new_array.stride_list_);
0508     swap(this->index_base_list_,new_array.index_base_list_);
0509     swap(this->origin_offset_,new_array.origin_offset_);
0510     swap(this->directional_offset_,new_array.directional_offset_);
0511     swap(this->num_elements_,new_array.num_elements_);
0512     swap(this->base_,new_array.base_);
0513     swap(this->allocated_elements_,new_array.allocated_elements_);
0514 
0515     return *this;
0516   }
0517 
0518 
0519   ~multi_array() {
0520     deallocate_space();
0521   }
0522 
0523 private:
0524   friend inline bool operator==(const multi_array& a, const multi_array& b) {
0525     return a.base() == b.base();
0526   }
0527 
0528   friend inline bool operator!=(const multi_array& a, const multi_array& b) {
0529     return !(a == b);
0530   }
0531 
0532   const super_type& base() const {
0533     return *this;
0534   }
0535 
0536   const Allocator& allocator() const {
0537     return alloc_base::get();
0538   }
0539 
0540   Allocator& allocator() {
0541     return alloc_base::get();
0542   }
0543 
0544   void allocate_space() {
0545     base_ = allocator().allocate(this->num_elements());
0546     this->set_base_ptr(base_);
0547     allocated_elements_ = this->num_elements();
0548     boost::alloc_construct_n(allocator(),base_,allocated_elements_);
0549   }
0550 
0551   void deallocate_space() {
0552     if(base_) {
0553       boost::alloc_destroy_n(allocator(),base_,allocated_elements_);
0554       allocator().deallocate(base_,allocated_elements_);
0555     }
0556   }
0557 
0558   typedef boost::array<size_type,NumDims> size_list;
0559   typedef boost::array<index,NumDims> index_list;
0560 
0561   T* base_;
0562   size_type allocated_elements_;
0563   enum {initial_base_ = 0};
0564 };
0565 
0566 } // namespace boost
0567 
0568 #if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 406)
0569 #  pragma GCC diagnostic pop
0570 #endif
0571 
0572 #endif