]> git.lyx.org Git - lyx.git/blob - boost/boost/multi_array/multi_array_ref.hpp
* src/MenuBackend.[Ch]: the specialMenu is now a real menu, not a
[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/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
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       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
314 protected:
315 #else
316 public:
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
362 private:
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
388 protected:
389 #else
390 public:
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
415 template <typename T, std::size_t NumDims>
416 class multi_array_ref :
417   public const_multi_array_ref<T,NumDims,T*>
418 {
419   typedef const_multi_array_ref<T,NumDims,T*> super_type;
420 public: 
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
621 protected:
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