]> git.sesse.net Git - casparcg/blob - dependencies64/boost/boost/multi_array/multi_array_ref.hpp
[general] Added cg_producer_registry as dependency in frame_producer_dependencies
[casparcg] / dependencies64 / boost / boost / multi_array / multi_array_ref.hpp
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/utility/enable_if.hpp"
30 #include "boost/array.hpp"
31 #include "boost/concept_check.hpp"
32 #include "boost/functional.hpp"
33 #include "boost/limits.hpp"
34 #include <algorithm>
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       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       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       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       CollectionConcept<SizeList> >();
168     BOOST_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       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   template <int NDims>
229   typename const_array_view<NDims>::type 
230   operator[](const detail::multi_array::
231              index_gen<NumDims,NDims>& indices)
232     const {
233     typedef typename const_array_view<NDims>::type return_type;
234     return
235       super_type::generate_array_view(boost::type<return_type>(),
236                                       indices,
237                                       shape(),
238                                       strides(),
239                                       index_bases(),
240                                       origin());
241   }
242   
243   const_iterator begin() const {
244     return const_iterator(*index_bases(),origin(),
245                           shape(),strides(),index_bases());
246   }
247
248   const_iterator end() const {
249     return const_iterator(*index_bases()+(index)*shape(),origin(),
250                           shape(),strides(),index_bases());
251   }
252
253   const_reverse_iterator rbegin() const {
254     return const_reverse_iterator(end());
255   }
256
257   const_reverse_iterator rend() const {
258     return const_reverse_iterator(begin());
259   }
260
261
262   template <typename OPtr>
263   bool operator==(const
264                   const_multi_array_ref<T,NumDims,OPtr>& rhs)
265     const {
266     if(std::equal(extent_list_.begin(),
267                   extent_list_.end(),
268                   rhs.extent_list_.begin()))
269       return std::equal(begin(),end(),rhs.begin());
270     else return false;
271   }
272
273   template <typename OPtr>
274   bool operator<(const
275                  const_multi_array_ref<T,NumDims,OPtr>& rhs)
276     const {
277     return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
278   }
279
280   template <typename OPtr>
281   bool operator!=(const
282                   const_multi_array_ref<T,NumDims,OPtr>& rhs)
283     const {
284     return !(*this == rhs);
285   }
286
287   template <typename OPtr>
288   bool operator>(const
289                  const_multi_array_ref<T,NumDims,OPtr>& rhs)
290     const {
291     return rhs < *this;
292   }
293
294   template <typename OPtr>
295   bool operator<=(const
296                  const_multi_array_ref<T,NumDims,OPtr>& rhs)
297     const {
298     return !(*this > rhs);
299   }
300
301   template <typename OPtr>
302   bool operator>=(const
303                  const_multi_array_ref<T,NumDims,OPtr>& rhs)
304     const {
305     return !(*this < rhs);
306   }
307
308
309 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
310 protected:
311 #else
312 public:
313 #endif
314
315   typedef boost::array<size_type,NumDims> size_list;
316   typedef boost::array<index,NumDims> index_list;
317
318   // This is used by multi_array, which is a subclass of this
319   void set_base_ptr(TPtr new_base) { base_ = new_base; }
320
321
322   // This constructor supports multi_array's default constructor
323   // and constructors from multi_array_ref, subarray, and array_view
324   explicit
325   const_multi_array_ref(TPtr base,
326                         const storage_order_type& so,
327                         const index * index_bases,
328                         const size_type* extents) :
329     base_(base), storage_(so), origin_offset_(0), directional_offset_(0)
330  {
331    // If index_bases or extents is null, then initialize the corresponding
332    // private data to zeroed lists.
333    if(index_bases) {
334      boost::detail::multi_array::
335        copy_n(index_bases,NumDims,index_base_list_.begin());
336    } else {
337      std::fill_n(index_base_list_.begin(),NumDims,0);
338    }
339    if(extents) {
340      init_multi_array_ref(extents);
341    } else {
342      boost::array<index,NumDims> extent_list;
343      extent_list.assign(0);
344      init_multi_array_ref(extent_list.begin());
345    }
346  }
347
348
349   TPtr base_;
350   storage_order_type storage_;
351   size_list extent_list_;
352   index_list stride_list_;
353   index_list index_base_list_;
354   index origin_offset_;
355   index directional_offset_;
356   size_type num_elements_;
357
358 private:
359   // const_multi_array_ref cannot be assigned to (no deep copies!)
360   const_multi_array_ref& operator=(const const_multi_array_ref& other);
361
362   void init_from_extent_gen(const
363                         detail::multi_array::
364                         extent_gen<NumDims>& ranges) { 
365     
366     typedef boost::array<index,NumDims> extent_list;
367
368     // get the index_base values
369     std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
370               index_base_list_.begin(),
371               boost::mem_fun_ref(&extent_range::start));
372
373     // calculate the extents
374     extent_list extents;
375     std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
376               extents.begin(),
377               boost::mem_fun_ref(&extent_range::size));
378
379     init_multi_array_ref(extents.begin());
380   }
381
382
383 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
384 protected:
385 #else
386 public:
387 #endif
388   // RG - move me!
389   template <class InputIterator>
390   void init_multi_array_ref(InputIterator extents_iter) {
391     boost::function_requires<InputIteratorConcept<InputIterator> >();
392
393     boost::detail::multi_array::
394       copy_n(extents_iter,num_dimensions(),extent_list_.begin());
395
396     // Calculate the array size
397     num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
398                             size_type(1),std::multiplies<size_type>());
399
400     this->compute_strides(stride_list_,extent_list_,storage_);
401
402     origin_offset_ =
403       this->calculate_origin_offset(stride_list_,extent_list_,
404                               storage_,index_base_list_);
405     directional_offset_ =
406       this->calculate_descending_dimension_offset(stride_list_,extent_list_,
407                                             storage_);
408   }
409 };
410
411 template <typename T, std::size_t NumDims>
412 class multi_array_ref :
413   public const_multi_array_ref<T,NumDims,T*>
414 {
415   typedef const_multi_array_ref<T,NumDims,T*> super_type;
416 public: 
417   typedef typename super_type::value_type value_type;
418   typedef typename super_type::reference reference;
419   typedef typename super_type::iterator iterator;
420   typedef typename super_type::reverse_iterator reverse_iterator;
421   typedef typename super_type::const_reference const_reference;
422   typedef typename super_type::const_iterator const_iterator;
423   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
424   typedef typename super_type::element element;
425   typedef typename super_type::size_type size_type;
426   typedef typename super_type::difference_type difference_type;
427   typedef typename super_type::index index;
428   typedef typename super_type::extent_range extent_range;
429
430   typedef typename super_type::storage_order_type storage_order_type;
431   typedef typename super_type::index_list index_list;
432   typedef typename super_type::size_list size_list;
433
434   template <std::size_t NDims>
435   struct const_array_view {
436     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
437   };
438
439   template <std::size_t NDims>
440   struct array_view {
441     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
442   };
443
444   template <class ExtentList>
445   explicit multi_array_ref(T* base, const ExtentList& extents) :
446     super_type(base,extents) {
447     boost::function_requires<
448       CollectionConcept<ExtentList> >();
449   }
450
451   template <class ExtentList>
452   explicit multi_array_ref(T* base, const ExtentList& extents,
453                            const general_storage_order<NumDims>& so) :
454     super_type(base,extents,so) {
455     boost::function_requires<
456       CollectionConcept<ExtentList> >();
457   }
458
459
460   explicit multi_array_ref(T* base,
461                            const detail::multi_array::
462                            extent_gen<NumDims>& ranges) :
463     super_type(base,ranges) { }
464
465
466   explicit multi_array_ref(T* base,
467                            const detail::multi_array::
468                            extent_gen<NumDims>&
469                              ranges,
470                            const general_storage_order<NumDims>& so) :
471     super_type(base,ranges,so) { }
472
473
474   // Assignment from other ConstMultiArray types.
475   template <typename ConstMultiArray>
476   multi_array_ref& operator=(const ConstMultiArray& other) {
477     function_requires< 
478       multi_array_concepts::
479       ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
480
481     // make sure the dimensions agree
482     BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
483     BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(),
484                             this->shape()));
485     // iterator-based copy
486     std::copy(other.begin(),other.end(),this->begin());
487     return *this;
488   }
489
490   multi_array_ref& operator=(const multi_array_ref& other) {
491     if (&other != this) {
492       // make sure the dimensions agree
493       
494       BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
495       BOOST_ASSERT(std::equal(other.shape(),
496                               other.shape()+this->num_dimensions(),
497                               this->shape()));
498       // iterator-based copy
499       std::copy(other.begin(),other.end(),this->begin());
500     }
501     return *this;
502   }
503
504   element* origin() { return super_type::base_+super_type::origin_offset_; }
505
506   element* data() { return super_type::base_; }
507
508   template <class IndexList>
509   element& operator()(const IndexList& indices) {
510     boost::function_requires<
511       CollectionConcept<IndexList> >();
512     return super_type::access_element(boost::type<element&>(),
513                                       indices,origin(),
514                                       this->shape(),this->strides(),
515                                       this->index_bases());
516   }
517
518
519   reference operator[](index idx) {
520     return super_type::access(boost::type<reference>(),
521                               idx,origin(),
522                               this->shape(),this->strides(),
523                               this->index_bases());
524   }
525
526
527   // See note attached to generate_array_view in base.hpp
528   template <int NDims>
529   typename array_view<NDims>::type 
530   operator[](const detail::multi_array::
531              index_gen<NumDims,NDims>& indices) {
532     typedef typename array_view<NDims>::type return_type;
533     return
534       super_type::generate_array_view(boost::type<return_type>(),
535                                       indices,
536                                       this->shape(),
537                                       this->strides(),
538                                       this->index_bases(),
539                                       origin());
540   }
541   
542   
543   iterator begin() {
544     return iterator(*this->index_bases(),origin(),this->shape(),
545                     this->strides(),this->index_bases());
546   }
547
548   iterator end() {
549     return iterator(*this->index_bases()+(index)*this->shape(),origin(),
550                     this->shape(),this->strides(),
551                     this->index_bases());
552   }
553
554   // rbegin() and rend() written naively to thwart MSVC ICE.
555   reverse_iterator rbegin() {
556     reverse_iterator ri(end());
557     return ri;
558   }
559
560   reverse_iterator rend() {
561     reverse_iterator ri(begin());
562     return ri;
563   }
564
565   // Using declarations don't seem to work for g++
566   // These are the proxies to work around this.
567
568   const element* origin() const { return super_type::origin(); }
569   const element* data() const { return super_type::data(); }
570
571   template <class IndexList>
572   const element& operator()(const IndexList& indices) const {
573     boost::function_requires<
574       CollectionConcept<IndexList> >();
575     return super_type::operator()(indices);
576   }
577
578   const_reference operator[](index idx) const {
579     return super_type::access(boost::type<const_reference>(),
580                               idx,origin(),
581                               this->shape(),this->strides(),
582                               this->index_bases());
583   }
584
585   // See note attached to generate_array_view in base.hpp
586   template <int NDims>
587   typename const_array_view<NDims>::type 
588   operator[](const detail::multi_array::
589              index_gen<NumDims,NDims>& indices)
590     const {
591     return super_type::operator[](indices);
592   }
593   
594   const_iterator begin() const {
595     return super_type::begin();
596   }
597
598   const_iterator end() const {
599     return super_type::end();
600   }
601
602   const_reverse_iterator rbegin() const {
603     return super_type::rbegin();
604   }
605
606   const_reverse_iterator rend() const {
607     return super_type::rend();
608   }
609
610 protected:
611   // This is only supplied to support multi_array's default constructor
612   explicit multi_array_ref(T* base,
613                            const storage_order_type& so,
614                            const index* index_bases,
615                            const size_type* extents) :
616     super_type(base,so,index_bases,extents) { }
617
618 };
619
620 } // namespace boost
621
622 #endif // BOOST_MULTI_ARRAY_REF_RG071801_HPP