PageRenderTime 64ms CodeModel.GetById 17ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 1ms

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

http://hadesmem.googlecode.com/
C++ Header | 633 lines | 482 code | 111 blank | 40 comment | 18 complexity | c9a97617573dceb1a55a343a110e30ed 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_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 <cstddef>
 35#include <functional>
 36#include <numeric>
 37
 38namespace boost {
 39
 40template <typename T, std::size_t NumDims,
 41  typename TPtr = const T*
 42>
 43class const_multi_array_ref :
 44    public detail::multi_array::multi_array_impl_base<T,NumDims>
 45{
 46  typedef detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
 47public: 
 48  typedef typename super_type::value_type value_type;
 49  typedef typename super_type::const_reference const_reference;
 50  typedef typename super_type::const_iterator const_iterator;
 51  typedef typename super_type::const_reverse_iterator const_reverse_iterator;
 52  typedef typename super_type::element element;
 53  typedef typename super_type::size_type size_type;
 54  typedef typename super_type::difference_type difference_type;
 55  typedef typename super_type::index index;
 56  typedef typename super_type::extent_range extent_range;
 57  typedef general_storage_order<NumDims> storage_order_type;
 58
 59  // template typedefs
 60  template <std::size_t NDims>
 61  struct const_array_view {
 62    typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
 63  };
 64
 65  template <std::size_t NDims>
 66  struct array_view {
 67    typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
 68  };
 69
 70#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
 71  // make const_multi_array_ref a friend of itself
 72  template <typename,std::size_t,typename>
 73  friend class const_multi_array_ref;
 74#endif
 75
 76  // This ensures that const_multi_array_ref types with different TPtr 
 77  // types can convert to each other
 78  template <typename OPtr>
 79  const_multi_array_ref(const const_multi_array_ref<T,NumDims,OPtr>& other)
 80    : base_(other.base_), storage_(other.storage_),
 81      extent_list_(other.extent_list_),
 82      stride_list_(other.stride_list_),
 83      index_base_list_(other.index_base_list_),
 84      origin_offset_(other.origin_offset_),
 85      directional_offset_(other.directional_offset_),
 86      num_elements_(other.num_elements_)  {  }
 87
 88  template <typename ExtentList>
 89  explicit const_multi_array_ref(TPtr base, const ExtentList& extents) :
 90    base_(base), storage_(c_storage_order()) {
 91    boost::function_requires<
 92      CollectionConcept<ExtentList> >();
 93
 94    index_base_list_.assign(0);
 95    init_multi_array_ref(extents.begin());
 96  }
 97  
 98  template <typename ExtentList>
 99  explicit const_multi_array_ref(TPtr base, const ExtentList& extents,
100                       const general_storage_order<NumDims>& so) : 
101    base_(base), storage_(so) {
102    boost::function_requires<
103      CollectionConcept<ExtentList> >();
104
105    index_base_list_.assign(0);
106    init_multi_array_ref(extents.begin());
107  }
108  
109  explicit const_multi_array_ref(TPtr base,
110                         const detail::multi_array::
111                         extent_gen<NumDims>& ranges) :
112    base_(base), storage_(c_storage_order()) {
113
114    init_from_extent_gen(ranges);
115  }
116  
117  explicit const_multi_array_ref(TPtr base,
118                           const detail::multi_array::
119                           extent_gen<NumDims>& ranges,
120                           const general_storage_order<NumDims>& so) :
121    base_(base), storage_(so) {
122
123    init_from_extent_gen(ranges);
124  }
125  
126  template <class InputIterator>
127  void assign(InputIterator begin, InputIterator end) {
128    boost::function_requires<InputIteratorConcept<InputIterator> >();
129
130    InputIterator in_iter = begin;
131    T* out_iter = base_;
132    std::size_t copy_count=0;
133    while (in_iter != end && copy_count < num_elements_) {
134      *out_iter++ = *in_iter++;
135      copy_count++;      
136    }
137  }
138
139  template <class BaseList>
140#ifdef BOOST_NO_SFINAE
141  void
142#else
143  typename
144  disable_if<typename boost::is_integral<BaseList>::type,void >::type
145#endif // BOOST_NO_SFINAE
146  reindex(const BaseList& values) {
147    boost::function_requires<
148      CollectionConcept<BaseList> >();
149    boost::detail::multi_array::
150      copy_n(values.begin(),num_dimensions(),index_base_list_.begin());
151    origin_offset_ =
152      this->calculate_origin_offset(stride_list_,extent_list_,
153                              storage_,index_base_list_);
154  }
155
156  void reindex(index value) {
157    index_base_list_.assign(value);
158    origin_offset_ =
159      this->calculate_origin_offset(stride_list_,extent_list_,
160                              storage_,index_base_list_);
161  }
162
163  template <typename SizeList>
164  void reshape(const SizeList& extents) {
165    boost::function_requires<
166      CollectionConcept<SizeList> >();
167    BOOST_ASSERT(num_elements_ ==
168                 std::accumulate(extents.begin(),extents.end(),
169                                 size_type(1),std::multiplies<size_type>()));
170
171    std::copy(extents.begin(),extents.end(),extent_list_.begin());
172    this->compute_strides(stride_list_,extent_list_,storage_);
173
174    origin_offset_ =
175      this->calculate_origin_offset(stride_list_,extent_list_,
176                              storage_,index_base_list_);
177  }
178
179  size_type num_dimensions() const { return NumDims; }
180
181  size_type size() const { return extent_list_.front(); }
182
183  // given reshaping functionality, this is the max possible size.
184  size_type max_size() const { return num_elements(); }
185
186  bool empty() const { return size() == 0; }
187
188  const size_type* shape() const {
189    return extent_list_.data();
190  }
191
192  const index* strides() const {
193    return stride_list_.data();
194  }
195
196  const element* origin() const { return base_+origin_offset_; }
197  const element* data() const { return base_; }
198
199  size_type num_elements() const { return num_elements_; }
200
201  const index* index_bases() const {
202    return index_base_list_.data();
203  }
204
205
206  const storage_order_type& storage_order() const {
207    return storage_;
208  }
209
210  template <typename IndexList>
211  const element& operator()(IndexList indices) const {
212    boost::function_requires<
213      CollectionConcept<IndexList> >();
214    return super_type::access_element(boost::type<const element&>(),
215                                      indices,origin(),
216                                      shape(),strides(),index_bases());
217  }
218
219  // Only allow const element access
220  const_reference operator[](index idx) const {
221    return super_type::access(boost::type<const_reference>(),
222                              idx,origin(),
223                              shape(),strides(),index_bases());
224  }
225
226  // see generate_array_view in base.hpp
227#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
228  template <int NDims>
229#else
230  template <int NumDims, int NDims> // else ICE
231#endif // BOOST_MSVC
232  typename const_array_view<NDims>::type 
233  operator[](const detail::multi_array::
234             index_gen<NumDims,NDims>& indices)
235    const {
236    typedef typename const_array_view<NDims>::type return_type;
237    return
238      super_type::generate_array_view(boost::type<return_type>(),
239                                      indices,
240                                      shape(),
241                                      strides(),
242                                      index_bases(),
243                                      origin());
244  }
245  
246  const_iterator begin() const {
247    return const_iterator(*index_bases(),origin(),
248                          shape(),strides(),index_bases());
249  }
250
251  const_iterator end() const {
252    return const_iterator(*index_bases()+(index)*shape(),origin(),
253                          shape(),strides(),index_bases());
254  }
255
256  const_reverse_iterator rbegin() const {
257    return const_reverse_iterator(end());
258  }
259
260  const_reverse_iterator rend() const {
261    return const_reverse_iterator(begin());
262  }
263
264
265  template <typename OPtr>
266  bool operator==(const
267                  const_multi_array_ref<T,NumDims,OPtr>& rhs)
268    const {
269    if(std::equal(extent_list_.begin(),
270                  extent_list_.end(),
271                  rhs.extent_list_.begin()))
272      return std::equal(begin(),end(),rhs.begin());
273    else return false;
274  }
275
276  template <typename OPtr>
277  bool operator<(const
278                 const_multi_array_ref<T,NumDims,OPtr>& rhs)
279    const {
280    return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
281  }
282
283  template <typename OPtr>
284  bool operator!=(const
285                  const_multi_array_ref<T,NumDims,OPtr>& rhs)
286    const {
287    return !(*this == rhs);
288  }
289
290  template <typename OPtr>
291  bool operator>(const
292                 const_multi_array_ref<T,NumDims,OPtr>& rhs)
293    const {
294    return rhs < *this;
295  }
296
297  template <typename OPtr>
298  bool operator<=(const
299                 const_multi_array_ref<T,NumDims,OPtr>& rhs)
300    const {
301    return !(*this > rhs);
302  }
303
304  template <typename OPtr>
305  bool operator>=(const
306                 const_multi_array_ref<T,NumDims,OPtr>& rhs)
307    const {
308    return !(*this < rhs);
309  }
310
311
312#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
313protected:
314#else
315public:
316#endif
317
318  typedef boost::array<size_type,NumDims> size_list;
319  typedef boost::array<index,NumDims> index_list;
320
321  // This is used by multi_array, which is a subclass of this
322  void set_base_ptr(TPtr new_base) { base_ = new_base; }
323
324
325  // This constructor supports multi_array's default constructor
326  // and constructors from multi_array_ref, subarray, and array_view
327  explicit
328  const_multi_array_ref(TPtr base,
329                        const storage_order_type& so,
330                        const index * index_bases,
331                        const size_type* extents) :
332    base_(base), storage_(so), origin_offset_(0), directional_offset_(0)
333 {
334   // If index_bases or extents is null, then initialize the corresponding
335   // private data to zeroed lists.
336   if(index_bases) {
337     boost::detail::multi_array::
338       copy_n(index_bases,NumDims,index_base_list_.begin());
339   } else {
340     std::fill_n(index_base_list_.begin(),NumDims,0);
341   }
342   if(extents) {
343     init_multi_array_ref(extents);
344   } else {
345     boost::array<index,NumDims> extent_list;
346     extent_list.assign(0);
347     init_multi_array_ref(extent_list.begin());
348   }
349 }
350
351
352  TPtr base_;
353  storage_order_type storage_;
354  size_list extent_list_;
355  index_list stride_list_;
356  index_list index_base_list_;
357  index origin_offset_;
358  index directional_offset_;
359  size_type num_elements_;
360
361private:
362  // const_multi_array_ref cannot be assigned to (no deep copies!)
363  const_multi_array_ref& operator=(const const_multi_array_ref& other);
364
365  void init_from_extent_gen(const
366                        detail::multi_array::
367                        extent_gen<NumDims>& ranges) { 
368    
369    typedef boost::array<index,NumDims> extent_list;
370
371    // get the index_base values
372    std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
373              index_base_list_.begin(),
374              boost::mem_fun_ref(&extent_range::start));
375
376    // calculate the extents
377    extent_list extents;
378    std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
379              extents.begin(),
380              boost::mem_fun_ref(&extent_range::size));
381
382    init_multi_array_ref(extents.begin());
383  }
384
385
386#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
387protected:
388#else
389public:
390#endif
391  // RG - move me!
392  template <class InputIterator>
393  void init_multi_array_ref(InputIterator extents_iter) {
394    boost::function_requires<InputIteratorConcept<InputIterator> >();
395
396    boost::detail::multi_array::
397      copy_n(extents_iter,num_dimensions(),extent_list_.begin());
398
399    // Calculate the array size
400    num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
401                            size_type(1),std::multiplies<size_type>());
402
403    this->compute_strides(stride_list_,extent_list_,storage_);
404
405    origin_offset_ =
406      this->calculate_origin_offset(stride_list_,extent_list_,
407                              storage_,index_base_list_);
408    directional_offset_ =
409      this->calculate_descending_dimension_offset(stride_list_,extent_list_,
410                                            storage_);
411  }
412};
413
414template <typename T, std::size_t NumDims>
415class multi_array_ref :
416  public const_multi_array_ref<T,NumDims,T*>
417{
418  typedef const_multi_array_ref<T,NumDims,T*> super_type;
419public: 
420  typedef typename super_type::value_type value_type;
421  typedef typename super_type::reference reference;
422  typedef typename super_type::iterator iterator;
423  typedef typename super_type::reverse_iterator reverse_iterator;
424  typedef typename super_type::const_reference const_reference;
425  typedef typename super_type::const_iterator const_iterator;
426  typedef typename super_type::const_reverse_iterator const_reverse_iterator;
427  typedef typename super_type::element element;
428  typedef typename super_type::size_type size_type;
429  typedef typename super_type::difference_type difference_type;
430  typedef typename super_type::index index;
431  typedef typename super_type::extent_range extent_range;
432
433  typedef typename super_type::storage_order_type storage_order_type;
434  typedef typename super_type::index_list index_list;
435  typedef typename super_type::size_list size_list;
436
437  template <std::size_t NDims>
438  struct const_array_view {
439    typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
440  };
441
442  template <std::size_t NDims>
443  struct array_view {
444    typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
445  };
446
447  template <class ExtentList>
448  explicit multi_array_ref(T* base, const ExtentList& extents) :
449    super_type(base,extents) {
450    boost::function_requires<
451      CollectionConcept<ExtentList> >();
452  }
453
454  template <class ExtentList>
455  explicit multi_array_ref(T* base, const ExtentList& extents,
456                           const general_storage_order<NumDims>& so) :
457    super_type(base,extents,so) {
458    boost::function_requires<
459      CollectionConcept<ExtentList> >();
460  }
461
462
463  explicit multi_array_ref(T* base,
464                           const detail::multi_array::
465                           extent_gen<NumDims>& ranges) :
466    super_type(base,ranges) { }
467
468
469  explicit multi_array_ref(T* base,
470                           const detail::multi_array::
471                           extent_gen<NumDims>&
472                             ranges,
473                           const general_storage_order<NumDims>& so) :
474    super_type(base,ranges,so) { }
475
476
477  // Assignment from other ConstMultiArray types.
478  template <typename ConstMultiArray>
479  multi_array_ref& operator=(const ConstMultiArray& other) {
480    function_requires< 
481      multi_array_concepts::
482      ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
483
484    // make sure the dimensions agree
485    BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
486    BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(),
487                            this->shape()));
488    // iterator-based copy
489    std::copy(other.begin(),other.end(),this->begin());
490    return *this;
491  }
492
493  multi_array_ref& operator=(const multi_array_ref& other) {
494    if (&other != this) {
495      // make sure the dimensions agree
496      
497      BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
498      BOOST_ASSERT(std::equal(other.shape(),
499                              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      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      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
621protected:
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