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