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