]> git.lyx.org Git - lyx.git/blob - boost/boost/multi_array/subarray.hpp
Boost 1.31.0
[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     return super_type::access_element(boost::type<const element&>(),
83                                       origin(),
84                                       indices,strides());
85   }
86
87   // see generate_array_view in base.hpp
88 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
89   template <int NDims>
90 #else
91   template <int NumDims, int NDims> // else ICE
92 #endif // BOOST_MSVC
93   typename const_array_view<NDims>::type 
94   operator[](const boost::detail::multi_array::
95              index_gen<NumDims,NDims>& indices)
96     const {
97     typedef typename const_array_view<NDims>::type return_type;
98     return
99       super_type::generate_array_view(boost::type<return_type>(),
100                                       indices,
101                                       shape(),
102                                       strides(),
103                                       index_bases(),
104                                       base_);
105   }
106
107   template <typename OPtr>
108   bool operator<(const const_sub_array<T,NumDims,OPtr>& rhs) const {
109     return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
110   }
111
112   template <typename OPtr>
113   bool operator==(const const_sub_array<T,NumDims,OPtr>& rhs) const {
114     if(std::equal(shape(),shape()+num_dimensions(),rhs.shape()))
115       return std::equal(begin(),end(),rhs.begin());
116     else return false;
117   }
118
119   template <typename OPtr>
120   bool operator!=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
121     return !(*this == rhs);
122   }
123
124   template <typename OPtr>
125   bool operator>(const const_sub_array<T,NumDims,OPtr>& rhs) const {
126     return rhs < *this;
127   }
128
129   template <typename OPtr>
130   bool operator<=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
131     return !(*this > rhs);
132   }
133
134   template <typename OPtr>
135   bool operator>=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
136     return !(*this < rhs);
137   }
138
139   const_iterator begin() const {
140     return const_iterator(*index_bases(),origin(),
141                           shape(),strides(),index_bases());
142   }
143
144   const_iterator end() const {
145     return const_iterator(*index_bases()+*shape(),origin(),
146                           shape(),strides(),index_bases());
147   }
148
149   const_reverse_iterator rbegin() const {
150     return const_reverse_iterator(end());
151   }
152
153   const_reverse_iterator rend() const {
154     return const_reverse_iterator(begin());
155   }
156
157   TPtr origin() const { return base_; }
158   size_type size() const { return extents_[0]; }
159   size_type max_size() const { return num_elements(); }
160   bool empty() const { return size() == 0; }
161   size_type num_dimensions() const { return NumDims; }
162   const size_type*  shape() const { return extents_; }
163   const index* strides() const { return strides_; }
164   const index* index_bases() const { return index_base_; }
165
166   size_type num_elements() const { 
167     return std::accumulate(shape(),shape() + num_dimensions(),
168                            size_type(1), std::multiplies<size_type>());
169   }
170
171
172 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
173 protected:
174   template <typename,std::size_t> friend class value_accessor_n;  
175   template <typename,std::size_t,typename> friend class const_sub_array;
176 #else    
177 public:  // Should be protected
178 #endif
179
180   const_sub_array (TPtr base,
181                  const size_type* extents,
182                  const index* strides,
183                  const index* index_base) :
184     base_(base), extents_(extents), strides_(strides),
185     index_base_(index_base) {
186   }
187
188   TPtr base_;
189   const size_type* extents_;
190   const index* strides_;
191   const index* index_base_;
192 private:
193   // const_sub_array cannot be assigned to (no deep copies!)
194   const_sub_array& operator=(const const_sub_array&);
195 };
196
197 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
198 //
199 // Compilers that don't support partial ordering may need help to
200 // disambiguate multi_array's templated constructors.  Even vc6/7 are
201 // capable of some limited SFINAE, so we take the most-general version
202 // out of the overload set with disable_non_sub_array.
203 //
204 template <typename T, std::size_t NumDims, typename TPtr>
205 char is_sub_array_help(const_sub_array<T,NumDims,TPtr>&);
206
207 char ( &is_sub_array_help(...) )[2];
208
209 template <class T>
210 struct is_sub_array
211 {
212     static T x;
213     BOOST_STATIC_CONSTANT(bool, value = sizeof((is_sub_array_help)(x)) == 1);
214 };
215
216 template <bool sub_array = false>
217 struct disable_non_sub_array_impl
218 {
219     // forming a pointer to a reference triggers SFINAE
220     typedef int& type; 
221 };
222
223 template <>
224 struct disable_non_sub_array_impl<true>
225 {
226     typedef int type;
227 };
228
229 template <class T>
230 struct disable_non_sub_array
231 {
232     typedef typename disable_non_sub_array_impl<is_sub_array<T>::value>::type type;
233 };
234 #endif
235
236 //
237 // sub_array
238 //    multi_array's proxy class to allow multiple overloads of
239 //    operator[] in order to provide a clean multi-dimensional array 
240 //    interface.
241 template <typename T, std::size_t NumDims>
242 class sub_array : public const_sub_array<T,NumDims,T*>
243 {
244   typedef const_sub_array<T,NumDims,T*> super_type;
245 public: 
246   typedef typename super_type::element element;
247   typedef typename super_type::reference reference;
248   typedef typename super_type::index index;
249   typedef typename super_type::size_type size_type;
250   typedef typename super_type::iterator iterator;
251   typedef typename super_type::reverse_iterator reverse_iterator;
252   typedef typename super_type::const_reference const_reference;
253   typedef typename super_type::const_iterator const_iterator;
254   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
255
256   // template typedefs
257   template <std::size_t NDims>
258   struct const_array_view {
259     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
260   };
261
262   template <std::size_t NDims>
263   struct array_view {
264     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
265   };
266
267   // Assignment from other ConstMultiArray types.
268   template <typename ConstMultiArray>
269   sub_array& operator=(const ConstMultiArray& other) {
270     function_requires< boost::detail::multi_array::ConstMultiArrayConcept< 
271         ConstMultiArray, NumDims> >();
272
273     // make sure the dimensions agree
274     assert(other.num_dimensions() == this->num_dimensions());
275     assert(std::equal(other.shape(),other.shape()+this->num_dimensions(),
276                       this->shape()));
277     // iterator-based copy
278     std::copy(other.begin(),other.end(),begin());
279     return *this;
280   }
281
282
283   sub_array& operator=(const sub_array& other) {
284     if (&other != this) {
285       // make sure the dimensions agree
286       assert(other.num_dimensions() == this->num_dimensions());
287       assert(std::equal(other.shape(),other.shape()+this->num_dimensions(),
288                         this->shape()));
289       // iterator-based copy
290       std::copy(other.begin(),other.end(),begin());
291     }
292     return *this;
293   }
294
295   T* origin() { return this->base_; }
296   const T* origin() const { return this->base_; }
297
298   reference operator[](index idx) {
299     return super_type::access(boost::type<reference>(),
300                               idx,this->base_,this->shape(),this->strides(),
301                               this->index_bases());
302   }
303
304   // see generate_array_view in base.hpp
305 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
306   template <int NDims>
307 #else
308   template <int NumDims, int NDims> // else ICE
309 #endif // BOOST_MSVC
310   typename array_view<NDims>::type 
311   operator[](const boost::detail::multi_array::
312              index_gen<NumDims,NDims>& indices) {
313     typedef typename array_view<NDims>::type return_type;
314     return
315       super_type::generate_array_view(boost::type<return_type>(),
316                                       indices,
317                                       this->shape(),
318                                       this->strides(),
319                                       this->index_bases(),
320                                       origin());
321   }
322
323   template <class IndexList>
324   element& operator()(const IndexList& indices) {
325     return super_type::access_element(boost::type<element&>(),
326                                       origin(),
327                                       indices,this->strides());
328   }
329
330   iterator begin() {
331     return iterator(*this->index_bases(),origin(),
332                     this->shape(),this->strides(),this->index_bases());
333   }
334
335   iterator end() {
336     return iterator(*this->index_bases()+*this->shape(),origin(),
337                     this->shape(),this->strides(),this->index_bases());
338   }
339
340   // RG - rbegin() and rend() written naively to thwart MSVC ICE.
341   reverse_iterator rbegin() {
342     reverse_iterator ri(end());
343     return ri;
344   }
345
346   reverse_iterator rend() {
347     reverse_iterator ri(begin());
348     return ri;
349   }
350
351   //
352   // proxies
353   //
354
355   template <class IndexList>
356   const element& operator()(const IndexList& indices) const {
357     return super_type::operator()(indices);
358   }
359
360   const_reference operator[](index idx) const {
361     return super_type::operator[](idx);
362   }
363
364   // see generate_array_view in base.hpp
365 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
366   template <int NDims>
367 #else
368   template <int NumDims, int NDims> // else ICE
369 #endif // BOOST_MSVC
370   typename const_array_view<NDims>::type 
371   operator[](const boost::detail::multi_array::
372              index_gen<NumDims,NDims>& indices)
373     const {
374     return super_type::operator[](indices);
375   }
376
377   const_iterator begin() const {
378     return super_type::begin();
379   }
380   
381   const_iterator end() const {
382     return super_type::end();
383   }
384
385   const_reverse_iterator rbegin() const {
386     return super_type::rbegin();
387   }
388
389   const_reverse_iterator rend() const {
390     return super_type::rend();
391   }
392
393 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
394 private:
395   template <typename,std::size_t> friend class value_accessor_n;
396 #else
397 public: // should be private
398 #endif
399
400   sub_array (T* base,
401             const size_type* extents,
402             const index* strides,
403             const index* index_base) :
404     super_type(base,extents,strides,index_base) {
405   }
406
407 };
408
409 } // namespace multi_array
410 } // namespace detail
411 //
412 // traits classes to get sub_array types
413 //
414 template <typename Array, int N>
415 class subarray_gen {
416   typedef typename Array::element element;
417 public:
418   typedef boost::detail::multi_array::sub_array<element,N> type;
419 };
420
421 template <typename Array, int N>
422 class const_subarray_gen {
423   typedef typename Array::element element;
424 public:
425   typedef boost::detail::multi_array::const_sub_array<element,N> type;  
426 };
427 } // namespace boost
428   
429 #endif // SUBARRAY_RG071801_HPP