]> git.lyx.org Git - lyx.git/blob - boost/boost/multi_array/subarray.hpp
* src/MenuBackend.[Ch]: the specialMenu is now a real menu, not a
[lyx.git] / boost / boost / multi_array / subarray.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 SUBARRAY_RG071801_HPP
14 #define SUBARRAY_RG071801_HPP
15
16 //
17 // subarray.hpp - used to implement standard operator[] on
18 // multi_arrays
19 //
20
21 #include "boost/multi_array/base.hpp"
22 #include "boost/multi_array/concept_checks.hpp"
23 #include "boost/limits.hpp"
24 #include "boost/type.hpp"
25 #include <algorithm>
26 #include <cstddef>
27 #include <functional>
28
29 namespace boost {
30 namespace detail {
31 namespace multi_array {
32
33 //
34 // const_sub_array
35 //    multi_array's proxy class to allow multiple overloads of
36 //    operator[] in order to provide a clean multi-dimensional array 
37 //    interface.
38 template <typename T, std::size_t NumDims, typename TPtr>
39 class const_sub_array :
40   public boost::detail::multi_array::multi_array_impl_base<T,NumDims>
41 {
42   typedef boost::detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
43 public: 
44   typedef typename super_type::value_type value_type;
45   typedef typename super_type::const_reference const_reference;
46   typedef typename super_type::const_iterator const_iterator;
47   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
48   typedef typename super_type::element element;
49   typedef typename super_type::size_type size_type;
50   typedef typename super_type::difference_type difference_type;
51   typedef typename super_type::index index;
52   typedef typename super_type::extent_range extent_range;
53
54   // template typedefs
55   template <std::size_t NDims>
56   struct const_array_view {
57     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
58   };
59
60   template <std::size_t NDims>
61   struct array_view {
62     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
63   };
64
65   // Allow default copy constructor as well.
66
67   template <typename OPtr>
68   const_sub_array (const const_sub_array<T,NumDims,OPtr>& rhs) :
69     base_(rhs.base_), extents_(rhs.extents_), strides_(rhs.strides_),
70     index_base_(rhs.index_base_) {
71   }
72
73   // const_sub_array always returns const types, regardless of its own
74   // constness.
75   const_reference operator[](index idx) const {
76     return super_type::access(boost::type<const_reference>(),
77                               idx,base_,shape(),strides(),index_bases());
78   }
79   
80   template <typename IndexList>
81   const element& operator()(const IndexList& indices) const {
82     boost::function_requires<
83       detail::multi_array::CollectionConcept<IndexList> >();
84     return super_type::access_element(boost::type<const element&>(),
85                                       indices,origin(),
86                                       shape(),strides(),index_bases());
87   }
88
89   // see generate_array_view in base.hpp
90 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
91   template <int NDims>
92 #else
93   template <int NumDims, int NDims> // else ICE
94 #endif // BOOST_MSVC
95   typename const_array_view<NDims>::type 
96   operator[](const boost::detail::multi_array::
97              index_gen<NumDims,NDims>& indices)
98     const {
99     typedef typename const_array_view<NDims>::type return_type;
100     return
101       super_type::generate_array_view(boost::type<return_type>(),
102                                       indices,
103                                       shape(),
104                                       strides(),
105                                       index_bases(),
106                                       base_);
107   }
108
109   template <typename OPtr>
110   bool operator<(const const_sub_array<T,NumDims,OPtr>& rhs) const {
111     return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
112   }
113
114   template <typename OPtr>
115   bool operator==(const const_sub_array<T,NumDims,OPtr>& rhs) const {
116     if(std::equal(shape(),shape()+num_dimensions(),rhs.shape()))
117       return std::equal(begin(),end(),rhs.begin());
118     else return false;
119   }
120
121   template <typename OPtr>
122   bool operator!=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
123     return !(*this == rhs);
124   }
125
126   template <typename OPtr>
127   bool operator>(const const_sub_array<T,NumDims,OPtr>& rhs) const {
128     return rhs < *this;
129   }
130
131   template <typename OPtr>
132   bool operator<=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
133     return !(*this > rhs);
134   }
135
136   template <typename OPtr>
137   bool operator>=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
138     return !(*this < rhs);
139   }
140
141   const_iterator begin() const {
142     return const_iterator(*index_bases(),origin(),
143                           shape(),strides(),index_bases());
144   }
145
146   const_iterator end() const {
147     return const_iterator(*index_bases()+(index)*shape(),origin(),
148                           shape(),strides(),index_bases());
149   }
150
151   const_reverse_iterator rbegin() const {
152     return const_reverse_iterator(end());
153   }
154
155   const_reverse_iterator rend() const {
156     return const_reverse_iterator(begin());
157   }
158
159   TPtr origin() const { return base_; }
160   size_type size() const { return extents_[0]; }
161   size_type max_size() const { return num_elements(); }
162   bool empty() const { return size() == 0; }
163   size_type num_dimensions() const { return NumDims; }
164   const size_type*  shape() const { return extents_; }
165   const index* strides() const { return strides_; }
166   const index* index_bases() const { return index_base_; }
167
168   size_type num_elements() const { 
169     return std::accumulate(shape(),shape() + num_dimensions(),
170                            size_type(1), std::multiplies<size_type>());
171   }
172
173
174 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
175 protected:
176   template <typename,std::size_t> friend class value_accessor_n;  
177   template <typename,std::size_t,typename> friend class const_sub_array;
178 #else    
179 public:  // Should be protected
180 #endif
181
182   const_sub_array (TPtr base,
183                  const size_type* extents,
184                  const index* strides,
185                  const index* index_base) :
186     base_(base), extents_(extents), strides_(strides),
187     index_base_(index_base) {
188   }
189
190   TPtr base_;
191   const size_type* extents_;
192   const index* strides_;
193   const index* index_base_;
194 private:
195   // const_sub_array cannot be assigned to (no deep copies!)
196   const_sub_array& operator=(const const_sub_array&);
197 };
198
199
200 //
201 // sub_array
202 //    multi_array's proxy class to allow multiple overloads of
203 //    operator[] in order to provide a clean multi-dimensional array 
204 //    interface.
205 template <typename T, std::size_t NumDims>
206 class sub_array : public const_sub_array<T,NumDims,T*>
207 {
208   typedef const_sub_array<T,NumDims,T*> super_type;
209 public: 
210   typedef typename super_type::element element;
211   typedef typename super_type::reference reference;
212   typedef typename super_type::index index;
213   typedef typename super_type::size_type size_type;
214   typedef typename super_type::iterator iterator;
215   typedef typename super_type::reverse_iterator reverse_iterator;
216   typedef typename super_type::const_reference const_reference;
217   typedef typename super_type::const_iterator const_iterator;
218   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
219
220   // template typedefs
221   template <std::size_t NDims>
222   struct const_array_view {
223     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
224   };
225
226   template <std::size_t NDims>
227   struct array_view {
228     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
229   };
230
231   // Assignment from other ConstMultiArray types.
232   template <typename ConstMultiArray>
233   sub_array& operator=(const ConstMultiArray& other) {
234     function_requires< boost::detail::multi_array::ConstMultiArrayConcept< 
235         ConstMultiArray, NumDims> >();
236
237     // make sure the dimensions agree
238     assert(other.num_dimensions() == this->num_dimensions());
239     assert(std::equal(other.shape(),other.shape()+this->num_dimensions(),
240                       this->shape()));
241     // iterator-based copy
242     std::copy(other.begin(),other.end(),begin());
243     return *this;
244   }
245
246
247   sub_array& operator=(const sub_array& other) {
248     if (&other != this) {
249       // make sure the dimensions agree
250       assert(other.num_dimensions() == this->num_dimensions());
251       assert(std::equal(other.shape(),other.shape()+this->num_dimensions(),
252                         this->shape()));
253       // iterator-based copy
254       std::copy(other.begin(),other.end(),begin());
255     }
256     return *this;
257   }
258
259   T* origin() { return this->base_; }
260   const T* origin() const { return this->base_; }
261
262   reference operator[](index idx) {
263     return super_type::access(boost::type<reference>(),
264                               idx,this->base_,this->shape(),this->strides(),
265                               this->index_bases());
266   }
267
268   // see generate_array_view in base.hpp
269 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
270   template <int NDims>
271 #else
272   template <int NumDims, int NDims> // else ICE
273 #endif // BOOST_MSVC
274   typename array_view<NDims>::type 
275   operator[](const boost::detail::multi_array::
276              index_gen<NumDims,NDims>& indices) {
277     typedef typename array_view<NDims>::type return_type;
278     return
279       super_type::generate_array_view(boost::type<return_type>(),
280                                       indices,
281                                       this->shape(),
282                                       this->strides(),
283                                       this->index_bases(),
284                                       origin());
285   }
286
287   template <class IndexList>
288   element& operator()(const IndexList& indices) {
289     boost::function_requires<
290       detail::multi_array::CollectionConcept<IndexList> >();
291     return super_type::access_element(boost::type<element&>(),
292                                       indices,origin(),
293                                       this->shape(),this->strides(),
294                                       this->index_bases());
295   }
296
297   iterator begin() {
298     return iterator(*this->index_bases(),origin(),
299                     this->shape(),this->strides(),this->index_bases());
300   }
301
302   iterator end() {
303     return iterator(*this->index_bases()+(index)*this->shape(),origin(),
304                     this->shape(),this->strides(),this->index_bases());
305   }
306
307   // RG - rbegin() and rend() written naively to thwart MSVC ICE.
308   reverse_iterator rbegin() {
309     reverse_iterator ri(end());
310     return ri;
311   }
312
313   reverse_iterator rend() {
314     reverse_iterator ri(begin());
315     return ri;
316   }
317
318   //
319   // proxies
320   //
321
322   template <class IndexList>
323   const element& operator()(const IndexList& indices) const {
324     boost::function_requires<
325       detail::multi_array::CollectionConcept<IndexList> >();
326     return super_type::operator()(indices);
327   }
328
329   const_reference operator[](index idx) const {
330     return super_type::operator[](idx);
331   }
332
333   // see generate_array_view in base.hpp
334 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
335   template <int NDims>
336 #else
337   template <int NumDims, int NDims> // else ICE
338 #endif // BOOST_MSVC
339   typename const_array_view<NDims>::type 
340   operator[](const boost::detail::multi_array::
341              index_gen<NumDims,NDims>& indices)
342     const {
343     return super_type::operator[](indices);
344   }
345
346   const_iterator begin() const {
347     return super_type::begin();
348   }
349   
350   const_iterator end() const {
351     return super_type::end();
352   }
353
354   const_reverse_iterator rbegin() const {
355     return super_type::rbegin();
356   }
357
358   const_reverse_iterator rend() const {
359     return super_type::rend();
360   }
361
362 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
363 private:
364   template <typename,std::size_t> friend class value_accessor_n;
365 #else
366 public: // should be private
367 #endif
368
369   sub_array (T* base,
370             const size_type* extents,
371             const index* strides,
372             const index* index_base) :
373     super_type(base,extents,strides,index_base) {
374   }
375
376 };
377
378 } // namespace multi_array
379 } // namespace detail
380 //
381 // traits classes to get sub_array types
382 //
383 template <typename Array, int N>
384 class subarray_gen {
385   typedef typename Array::element element;
386 public:
387   typedef boost::detail::multi_array::sub_array<element,N> type;
388 };
389
390 template <typename Array, int N>
391 class const_subarray_gen {
392   typedef typename Array::element element;
393 public:
394   typedef boost::detail::multi_array::const_sub_array<element,N> type;  
395 };
396 } // namespace boost
397   
398 #endif // SUBARRAY_RG071801_HPP