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