]> git.lyx.org Git - lyx.git/blob - boost/boost/multi_array/multi_array_ref.hpp
update boost
[lyx.git] / boost / boost / multi_array / multi_array_ref.hpp
1 // Copyright (C) 2002 Ronald Garcia
2 //
3 // Permission to copy, use, sell and distribute this software is granted
4 // provided this copyright notice appears in all copies. 
5 // Permission to modify the code and to distribute modified code is granted
6 // provided this copyright notice appears in all copies, and a notice 
7 // that the code was modified is included with the copyright notice.
8 //
9 // This software is provided "as is" without express or implied warranty, 
10 // and with no claim as to its suitability for any purpose.
11 //
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/array.hpp"
29 #include "boost/concept_check.hpp"
30 #include "boost/functional.hpp"
31 #include "boost/limits.hpp"
32 #include <algorithm>
33 #include <cassert>
34 #include <cstddef>
35 #include <functional>
36 #include <numeric>
37
38 namespace boost {
39
40 template <typename T, std::size_t NumDims,
41   typename TPtr = const T*
42 >
43 class 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;
47 public: 
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_iter_base const_iter_base;
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
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   template <typename OPtr>
78   const_multi_array_ref(const const_multi_array_ref<T,NumDims,
79                         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   void reindex(const BaseList& values) {
141     boost::function_requires<
142       detail::multi_array::CollectionConcept<BaseList> >();
143     boost::copy_n(values.begin(),num_dimensions(),index_base_list_.begin());
144     origin_offset_ =
145       calculate_origin_offset(stride_list_,extent_list_,
146                               storage_,index_base_list_);
147   }
148
149   void reindex(index value) {
150     index_base_list_.assign(value);
151     origin_offset_ =
152       calculate_origin_offset(stride_list_,extent_list_,
153                               storage_,index_base_list_);
154   }
155
156   template <typename SizeList>
157   void reshape(const SizeList& extents) {
158     boost::function_requires<
159       detail::multi_array::CollectionConcept<SizeList> >();
160     assert(num_elements_ ==
161            std::accumulate(extents.begin(),extents.end(),
162                             size_type(1),std::multiplies<size_type>()));
163
164     std::copy(extents.begin(),extents.end(),extent_list_.begin());
165     compute_strides(stride_list_,extent_list_,storage_);
166
167     origin_offset_ =
168       calculate_origin_offset(stride_list_,extent_list_,
169                               storage_,index_base_list_);
170   }
171
172   size_type num_dimensions() const { return NumDims; }
173
174   size_type size() const { return extent_list_.front(); }
175
176   // given reshaping functionality, this is the max possible size.
177   size_type max_size() const { return num_elements(); }
178
179   bool empty() const { return size() == 0; }
180
181   const size_type* shape() const {
182     return extent_list_.data();
183   }
184
185   const index* strides() const {
186     return stride_list_.data();
187   }
188
189   const element* origin() const { return base_+origin_offset_; }
190   const element* data() const { return base_; }
191
192   size_type num_elements() const { return num_elements_; }
193
194   const index* index_bases() const {
195     return index_base_list_.data();
196   }
197
198   template <typename IndexList>
199   const element& operator()(IndexList indices) const {
200     boost::function_requires<
201       detail::multi_array::CollectionConcept<IndexList> >();
202     return super_type::access_element(boost::type<const element&>(),
203                                       origin(),
204                                       indices,strides());
205   }
206
207   // Only allow const element access
208   const_reference operator[](index idx) const {
209     return super_type::access(boost::type<const_reference>(),
210                               idx,origin(),
211                               shape(),strides(),index_bases());
212   }
213
214   // see generate_array_view in base.hpp
215 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
216   template <int NDims>
217 #else
218   template <int NumDims, int NDims> // else ICE
219 #endif // BOOST_MSVC
220   typename const_array_view<NDims>::type 
221   operator[](const detail::multi_array::
222              index_gen<NumDims,NDims>& indices)
223     const {
224     typedef typename const_array_view<NDims>::type return_type;
225     return
226       super_type::generate_array_view(boost::type<return_type>(),
227                                       indices,
228                                       shape(),
229                                       strides(),
230                                       index_bases(),
231                                       origin());
232   }
233   
234   const_iterator begin() const {
235     return const_iterator(const_iter_base(*index_bases(),origin(),
236                                    shape(),strides(),index_bases()));
237   }
238
239   const_iterator end() const {
240     return const_iterator(const_iter_base(*index_bases()+*shape(),origin(),
241                                    shape(),strides(),index_bases()));
242   }
243
244   const_reverse_iterator rbegin() const {
245     return const_reverse_iterator(end());
246   }
247
248   const_reverse_iterator rend() const {
249     return const_reverse_iterator(begin());
250   }
251
252
253   template <typename OPtr>
254   bool operator==(const
255                   const_multi_array_ref<T,NumDims,OPtr>& rhs)
256     const {
257     if(std::equal(extent_list_.begin(),
258                   extent_list_.end(),
259                   rhs.extent_list_.begin()))
260       return std::equal(begin(),end(),rhs.begin());
261     else return false;
262   }
263
264   template <typename OPtr>
265   bool operator<(const
266                  const_multi_array_ref<T,NumDims,OPtr>& rhs)
267     const {
268     return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
269   }
270
271   template <typename OPtr>
272   bool operator!=(const
273                   const_multi_array_ref<T,NumDims,OPtr>& rhs)
274     const {
275     return !(*this == rhs);
276   }
277
278   template <typename OPtr>
279   bool operator>(const
280                  const_multi_array_ref<T,NumDims,OPtr>& rhs)
281     const {
282     return rhs < *this;
283   }
284
285   template <typename OPtr>
286   bool operator<=(const
287                  const_multi_array_ref<T,NumDims,OPtr>& rhs)
288     const {
289     return !(*this > rhs);
290   }
291
292   template <typename OPtr>
293   bool operator>=(const
294                  const_multi_array_ref<T,NumDims,OPtr>& rhs)
295     const {
296     return !(*this < rhs);
297   }
298
299 // This ensures that const_multi_array_ref types with different TPtr 
300 // types can convert to each other
301 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
302 protected:
303 #else
304 public:
305 #endif
306   // This is used by multi_array, which is a subclass of this
307   void set_base_ptr(TPtr new_base) { base_ = new_base; }
308
309   template <typename OPtr>
310   const_multi_array_ref(const detail::multi_array::
311                   const_sub_array<T,NumDims,OPtr>& rhs)
312     : base_(rhs.origin()),
313       storage_(c_storage_order()),
314       origin_offset_(0), directional_offset_(0),
315       num_elements_(rhs.num_elements())
316   {
317     using boost::copy_n;
318     copy_n(rhs.shape(),rhs.num_dimensions(),extent_list_.begin());
319     copy_n(rhs.strides(),rhs.num_dimensions(),stride_list_.begin());
320     copy_n(rhs.index_bases(),rhs.num_dimensions(),index_base_list_.begin());
321   }
322
323   typedef boost::array<size_type,NumDims> size_list;
324   typedef boost::array<index,NumDims> index_list;
325
326   TPtr base_;
327   general_storage_order<NumDims> storage_;
328   size_list extent_list_;
329   index_list stride_list_;
330   index_list index_base_list_;
331   index origin_offset_;
332   index directional_offset_;
333   size_type num_elements_;
334
335 private:
336   // const_multi_array_ref cannot be assigned to (no deep copies!)
337   const_multi_array_ref& operator=(const const_multi_array_ref& other);
338
339   void init_from_extent_gen(const
340                         detail::multi_array::
341                         extent_gen<NumDims>& ranges) { 
342     
343     typedef boost::array<index,NumDims> extent_list;
344
345     // get the index_base values
346     std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
347               index_base_list_.begin(),
348               boost::mem_fun_ref(&extent_range::start));
349
350     // calculate the extents
351     extent_list extents;
352     std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
353               extents.begin(),
354               boost::mem_fun_ref(&extent_range::size));
355
356     init_multi_array_ref(extents.begin());
357   }
358
359
360   template <class InputIterator>
361   void init_multi_array_ref(InputIterator extents_iter) {
362     boost::function_requires<InputIteratorConcept<InputIterator> >();
363
364     boost::copy_n(extents_iter,num_dimensions(),extent_list_.begin());
365
366     // Calculate the array size
367     num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
368                             1,std::multiplies<index>());
369     assert(num_elements_ != 0);
370
371     compute_strides(stride_list_,extent_list_,storage_);
372
373     origin_offset_ =
374       calculate_origin_offset(stride_list_,extent_list_,
375                               storage_,index_base_list_);
376     directional_offset_ =
377       calculate_descending_dimension_offset(stride_list_,extent_list_,
378                                             storage_);
379   }
380 };
381
382
383 template <typename T, std::size_t NumDims>
384 class multi_array_ref :
385   public const_multi_array_ref<T,NumDims,T*>
386 {
387   typedef const_multi_array_ref<T,NumDims,T*> super_type;
388 public: 
389   typedef typename super_type::value_type value_type;
390   typedef typename super_type::reference reference;
391   typedef typename super_type::iterator iterator;
392   typedef typename super_type::iter_base iter_base;
393   typedef typename super_type::reverse_iterator reverse_iterator;
394   typedef typename super_type::const_reference const_reference;
395   typedef typename super_type::const_iterator const_iterator;
396   typedef typename super_type::const_iter_base const_iter_base;
397   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
398   typedef typename super_type::element element;
399   typedef typename super_type::size_type size_type;
400   typedef typename super_type::difference_type difference_type;
401   typedef typename super_type::index index;
402   typedef typename super_type::extent_range extent_range;
403
404
405
406   template <std::size_t NDims>
407   struct const_array_view {
408     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
409   };
410
411   template <std::size_t NDims>
412   struct array_view {
413     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
414   };
415
416   template <class ExtentList>
417   explicit multi_array_ref(T* base, const ExtentList& extents) :
418     super_type(base,extents) {
419     boost::function_requires<
420       detail::multi_array::CollectionConcept<ExtentList> >();
421   }
422
423   template <class ExtentList>
424   explicit multi_array_ref(T* base, const ExtentList& extents,
425                            const general_storage_order<NumDims>& so) :
426     super_type(base,extents,so) {
427     boost::function_requires<
428       detail::multi_array::CollectionConcept<ExtentList> >();
429   }
430
431
432   explicit multi_array_ref(T* base,
433                            const detail::multi_array::
434                            extent_gen<NumDims>& ranges) :
435     super_type(base,ranges) { }
436
437
438   explicit multi_array_ref(T* base,
439                            const detail::multi_array::
440                            extent_gen<NumDims>&
441                              ranges,
442                            const general_storage_order<NumDims>& so) :
443     super_type(base,ranges,so) { }
444
445   template <typename OPtr>
446   multi_array_ref(const detail::multi_array::
447                   const_sub_array<T,NumDims,OPtr>& rhs)
448     : super_type(rhs) {} 
449
450   // Assignment from other ConstMultiArray types.
451   template <typename ConstMultiArray>
452   multi_array_ref& operator=(const ConstMultiArray& other) {
453     function_requires< 
454       detail::multi_array::
455       ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
456
457     // make sure the dimensions agree
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     return *this;
464   }
465
466   multi_array_ref& operator=(const multi_array_ref& other) {
467     if (&other != this) {
468       // make sure the dimensions agree
469       
470       assert(other.num_dimensions() == num_dimensions());
471       assert(std::equal(other.shape(),other.shape()+num_dimensions(),
472                         shape()));
473       // iterator-based copy
474       std::copy(other.begin(),other.end(),begin());
475     }
476     return *this;
477   }
478
479   element* origin() { return base_+origin_offset_; }
480
481   element* data() { return base_; }
482
483   template <class IndexList>
484   element& operator()(const IndexList& indices) {
485   boost::function_requires<
486     detail::multi_array::CollectionConcept<IndexList> >();
487   return super_type::access_element(boost::type<element&>(),
488                                       origin(),
489                                       indices,strides());
490   }
491
492
493   reference operator[](index idx) {
494     return super_type::access(boost::type<reference>(),
495                               idx,origin(),
496                               shape(),strides(),
497                               index_bases());
498   }
499
500
501   // See note attached to generate_array_view in base.hpp
502 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
503   template <int NDims>
504 #else
505   template <int NumDims, int NDims> // else ICE
506 #endif // BOOST_MSVC
507   typename array_view<NDims>::type 
508   operator[](const detail::multi_array::
509              index_gen<NumDims,NDims>& indices) {
510     typedef typename array_view<NDims>::type return_type;
511     return
512       super_type::generate_array_view(boost::type<return_type>(),
513                                       indices,
514                                       shape(),
515                                       strides(),
516                                       index_bases(),
517                                       origin());
518   }
519   
520   
521   iterator begin() {
522     return iterator(iter_base(*index_bases(),origin(),shape(),
523                               strides(),index_bases()));
524   }
525
526   iterator end() {
527     return iterator(iter_base(*index_bases()+*shape(),origin(),
528                               shape(),strides(),index_bases()));
529   }
530
531   // RG - rbegin() and rend() written naively to thwart MSVC ICE.
532   reverse_iterator rbegin() {
533     reverse_iterator ri(end());
534     return ri;
535   }
536
537   reverse_iterator rend() {
538     reverse_iterator ri(begin());
539     return ri;
540   }
541
542   // Using declarations don't seem to work for g++
543   // These are the proxies to work around this.
544
545   const element* origin() const { return super_type::origin(); }
546   const element* data() const { return super_type::data(); }
547
548   template <class IndexList>
549   const element& operator()(const IndexList& indices) const {
550     boost::function_requires<
551       detail::multi_array::CollectionConcept<IndexList> >();
552     return super_type::operator()(indices);
553   }
554
555   const_reference operator[](index idx) const {
556     return super_type::access(boost::type<const_reference>(),
557                               idx,origin(),
558                               shape(),strides(),index_bases());
559   }
560
561   // See note attached to generate_array_view in base.hpp
562 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
563   template <int NDims>
564 #else
565   template <int NumDims, int NDims> // else ICE
566 #endif // BOOST_MSVC
567   typename const_array_view<NDims>::type 
568   operator[](const detail::multi_array::
569              index_gen<NumDims,NDims>& indices)
570     const {
571     return super_type::operator[](indices);
572   }
573   
574   const_iterator begin() const {
575     return super_type::begin();
576   }
577
578   const_iterator end() const {
579     return super_type::end();
580   }
581
582   const_reverse_iterator rbegin() const {
583     return super_type::rbegin();
584   }
585
586   const_reverse_iterator rend() const {
587     return super_type::rend();
588   }
589 };
590
591 } // namespace boost
592
593 #endif // BOOST_MULTI_ARRAY_REF_RG071801_HPP