Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/multi_array/multi_array_ref.hpp @ 44

Last change on this file since 44 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 19.7 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 <cassert>
35#include <cstddef>
36#include <functional>
37#include <numeric>
38
39namespace boost {
40
41template <typename T, std::size_t NumDims,
42  typename TPtr = const T*
43>
44class 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;
48public: 
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
314protected:
315#else
316public:
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
362private:
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
388protected:
389#else
390public:
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
415template <typename T, std::size_t NumDims>
416class multi_array_ref :
417  public const_multi_array_ref<T,NumDims,T*>
418{
419  typedef const_multi_array_ref<T,NumDims,T*> super_type;
420public: 
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
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.