source: XIOS/dev/dev_olga/src/extern/boost/include/boost/multi_array/multi_array_ref.hpp @ 1022

Last change on this file since 1022 was 1022, checked in by mhnguyen, 7 years ago
File size: 19.8 KB
Line 
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      detail::multi_array::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      detail::multi_array::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      detail::multi_array::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      detail::multi_array::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      detail::multi_array::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      detail::multi_array::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      detail::multi_array::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      detail::multi_array::
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      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
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
Note: See TracBrowser for help on using the repository browser.