]> git.lyx.org Git - lyx.git/blob - boost/boost/multi_array/view.hpp
* src/MenuBackend.[Ch]: the specialMenu is now a real menu, not a
[lyx.git] / boost / boost / multi_array / view.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_VIEW_RG071301_HPP
14 #define BOOST_MULTI_ARRAY_VIEW_RG071301_HPP
15
16 //
17 // view.hpp - code for creating "views" of array data.
18 //
19
20 #include "boost/multi_array/base.hpp"
21 #include "boost/multi_array/concept_checks.hpp"
22 #include "boost/multi_array/iterator.hpp"
23 #include "boost/multi_array/storage_order.hpp"
24 #include "boost/multi_array/subarray.hpp"
25 #include "boost/multi_array/algorithm.hpp"
26 #include "boost/type_traits/is_integral.hpp"
27 #include "boost/array.hpp"
28 #include "boost/limits.hpp"
29 #include <algorithm>
30 #include <cstddef>
31 #include <functional>
32 #include <numeric>
33
34 namespace boost {
35 namespace detail {
36 namespace multi_array {
37
38 // TPtr = const T* defaulted in base.hpp
39 template <typename T, std::size_t NumDims, typename TPtr>
40 class const_multi_array_view :
41     public boost::detail::multi_array::multi_array_impl_base<T,NumDims>
42 {
43   typedef boost::detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
44 public: 
45   typedef typename super_type::value_type value_type;
46   typedef typename super_type::const_reference const_reference;
47   typedef typename super_type::const_iterator const_iterator;
48   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
49   typedef typename super_type::element element;
50   typedef typename super_type::size_type size_type;
51   typedef typename super_type::difference_type difference_type;
52   typedef typename super_type::index index;
53   typedef typename super_type::extent_range extent_range;
54
55   // template typedefs
56   template <std::size_t NDims>
57   struct const_array_view {
58     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
59   };
60
61   template <std::size_t NDims>
62   struct array_view {
63     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
64   };
65
66   template <typename OPtr>
67   const_multi_array_view(const 
68                          const_multi_array_view<T,NumDims,OPtr>& other) :
69     base_(other.base_), origin_offset_(other.origin_offset_),
70     num_elements_(other.num_elements_), extent_list_(other.extent_list_),
71     stride_list_(other.stride_list_), index_base_list_(other.index_base_list_)
72   { }
73
74
75   template <class BaseList>
76 #ifdef BOOST_NO_SFINAE
77   void
78 #else
79   typename
80   disable_if<typename boost::is_integral<BaseList>::type,void >::type
81 #endif
82   reindex(const BaseList& values) {
83     boost::function_requires<
84       detail::multi_array::CollectionConcept<BaseList> >();
85     boost::detail::multi_array::
86       copy_n(values.begin(),num_dimensions(),index_base_list_.begin());
87     origin_offset_ =
88       this->calculate_indexing_offset(stride_list_,index_base_list_);
89   }
90
91   void reindex(index value) {
92     index_base_list_.assign(value);
93     origin_offset_ =
94       this->calculate_indexing_offset(stride_list_,index_base_list_);
95   }
96
97   size_type num_dimensions() const { return NumDims; }
98
99   size_type size() const { return extent_list_.front(); }
100   size_type max_size() const { return num_elements(); }
101   bool empty() const { return size() == 0; }
102
103   const size_type* shape() const {
104     return extent_list_.data();
105   }
106
107   const index* strides() const {
108     return stride_list_.data();
109   }
110
111   const T* origin() const { return base_+origin_offset_; }
112
113   size_type num_elements() const { return num_elements_; }
114
115   const index* index_bases() const {
116     return index_base_list_.data();
117   }
118
119   template <typename IndexList>
120   const element& operator()(IndexList indices) const {
121     boost::function_requires<
122       detail::multi_array::CollectionConcept<IndexList> >();
123     return super_type::access_element(boost::type<const element&>(),
124                                       indices,origin(),
125                                       shape(),strides(),index_bases());
126   }
127
128   // Only allow const element access
129   const_reference operator[](index idx) const {
130     return super_type::access(boost::type<const_reference>(),
131                               idx,origin(),
132                               shape(),strides(),
133                               index_bases());
134   }
135
136   // see generate_array_view in base.hpp
137 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
138   template <int NDims>
139 #else
140   template <int NumDims, int NDims> // else ICE
141 #endif // BOOST_MSVC
142   typename const_array_view<NDims>::type 
143   operator[](const boost::detail::multi_array::
144              index_gen<NumDims,NDims>& indices)
145     const {
146     typedef typename const_array_view<NDims>::type return_type;
147     return
148       super_type::generate_array_view(boost::type<return_type>(),
149                                       indices,
150                                       shape(),
151                                       strides(),
152                                       index_bases(),
153                                       origin());
154   }
155   const_iterator begin() const {
156     return const_iterator(*index_bases(),origin(),
157                           shape(),strides(),index_bases());
158   }
159
160   const_iterator end() const {
161     return const_iterator(*index_bases()+(index)*shape(),origin(),
162                           shape(),strides(),index_bases());
163   }
164   
165   const_reverse_iterator rbegin() const {
166     return const_reverse_iterator(end());
167   }
168
169   const_reverse_iterator rend() const {
170     return const_reverse_iterator(begin());
171   }
172
173
174   template <typename OPtr>
175   bool operator==(const
176                   const_multi_array_view<T,NumDims,OPtr>& rhs)
177     const {
178     if(std::equal(extent_list_.begin(),
179                   extent_list_.end(),
180                   rhs.extent_list_.begin()))
181       return std::equal(begin(),end(),rhs.begin());
182     else return false;
183   }
184
185   template <typename OPtr>
186   bool operator<(const
187                  const_multi_array_view<T,NumDims,OPtr>& rhs)
188     const {
189     return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
190   }
191
192   template <typename OPtr>
193   bool operator!=(const
194                   const_multi_array_view<T,NumDims,OPtr>& rhs)
195     const {
196     return !(*this == rhs);
197   }
198
199   template <typename OPtr>
200   bool operator>(const
201                  const_multi_array_view<T,NumDims,OPtr>& rhs)
202     const {
203     return rhs < *this;
204   }
205
206   template <typename OPtr>
207   bool operator<=(const
208                  const_multi_array_view<T,NumDims,OPtr>& rhs)
209     const {
210     return !(*this > rhs);
211   }
212
213   template <typename OPtr>
214   bool operator>=(const
215                  const_multi_array_view<T,NumDims,OPtr>& rhs)
216     const {
217     return !(*this < rhs);
218   }
219
220
221 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
222 protected:
223   template <typename,std::size_t> friend class multi_array_impl_base;
224   template <typename,std::size_t,typename> friend class const_multi_array_view;
225 #else
226 public: // should be protected
227 #endif
228
229   // This constructor is used by multi_array_impl_base::generate_array_view
230   // to create strides  
231   template <typename ExtentList, typename Index>
232   explicit const_multi_array_view(TPtr base,
233                            const ExtentList& extents,
234                            const boost::array<Index,NumDims>& strides): 
235     base_(base), origin_offset_(0) {
236
237     index_base_list_.assign(0);
238
239     // Get the extents and strides
240     boost::detail::multi_array::
241       copy_n(extents.begin(),NumDims,extent_list_.begin());
242     boost::detail::multi_array::
243       copy_n(strides.begin(),NumDims,stride_list_.begin());
244
245     // Calculate the array size
246     num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
247                             size_type(1),std::multiplies<size_type>());
248 #if 0
249     assert(num_elements_ != 0);
250 #endif
251   }
252
253   typedef boost::array<size_type,NumDims> size_list;
254   typedef boost::array<index,NumDims> index_list;
255
256   TPtr base_;
257   index origin_offset_;
258   size_type num_elements_;
259   size_list extent_list_;
260   index_list stride_list_;
261   index_list index_base_list_;
262
263 private:
264   // const_multi_array_view cannot be assigned to (no deep copies!)
265   const_multi_array_view& operator=(const const_multi_array_view& other);
266 };
267
268
269 template <typename T, std::size_t NumDims>
270 class multi_array_view :
271   public const_multi_array_view<T,NumDims,T*>
272 {
273   typedef const_multi_array_view<T,NumDims,T*> super_type;
274 public: 
275   typedef typename super_type::value_type value_type;
276   typedef typename super_type::reference reference;
277   typedef typename super_type::iterator iterator;
278   typedef typename super_type::reverse_iterator reverse_iterator;
279   typedef typename super_type::const_reference const_reference;
280   typedef typename super_type::const_iterator const_iterator;
281   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
282   typedef typename super_type::element element;
283   typedef typename super_type::size_type size_type;
284   typedef typename super_type::difference_type difference_type;
285   typedef typename super_type::index index;
286   typedef typename super_type::extent_range extent_range;
287
288   // template typedefs
289   template <std::size_t NDims>
290   struct const_array_view {
291     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
292   };
293
294   template <std::size_t NDims>
295   struct array_view {
296     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
297   };
298
299   // Assignment from other ConstMultiArray types.
300   template <typename ConstMultiArray>
301   multi_array_view& operator=(const ConstMultiArray& other) {
302     function_requires< 
303       boost::detail::multi_array::
304       ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
305
306     // make sure the dimensions agree
307     assert(other.num_dimensions() == this->num_dimensions());
308     assert(std::equal(other.shape(),other.shape()+this->num_dimensions(),
309                       this->shape()));
310     // iterator-based copy
311     std::copy(other.begin(),other.end(),begin());
312     return *this;
313   }
314
315
316   multi_array_view& operator=(const multi_array_view& other) {
317     if (&other != this) {
318       // make sure the dimensions agree
319       assert(other.num_dimensions() == this->num_dimensions());
320       assert(std::equal(other.shape(),other.shape()+this->num_dimensions(),
321                         this->shape()));
322       // iterator-based copy
323       std::copy(other.begin(),other.end(),begin());
324     }
325     return *this;
326   }
327
328   element* origin() { return this->base_+this->origin_offset_; }
329
330   template <class IndexList>
331   element& operator()(const IndexList& indices) {
332     boost::function_requires<
333       detail::multi_array::CollectionConcept<IndexList> >();
334     return super_type::access_element(boost::type<element&>(),
335                                       indices,origin(),
336                                       this->shape(),this->strides(),
337                                       this->index_bases());
338   }
339
340
341   reference operator[](index idx) {
342     return super_type::access(boost::type<reference>(),
343                               idx,origin(),
344                               this->shape(),this->strides(),
345                               this->index_bases());
346   }
347
348
349   // see generate_array_view in base.hpp
350 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
351   template <int NDims>
352 #else
353   template <int NumDims, int NDims> // else ICE
354 #endif // BOOST_MSVC
355   typename array_view<NDims>::type 
356   operator[](const boost::detail::multi_array::
357              index_gen<NumDims,NDims>& indices) {
358     typedef typename array_view<NDims>::type return_type;
359     return
360       super_type::generate_array_view(boost::type<return_type>(),
361                                       indices,
362                                       this->shape(),
363                                       this->strides(),
364                                       this->index_bases(),
365                                       origin());
366   }
367   
368   
369   iterator begin() {
370     return iterator(*this->index_bases(),origin(),
371                     this->shape(),this->strides(),
372                     this->index_bases());
373   }
374
375   iterator end() {
376     return iterator(*this->index_bases()+(index)*this->shape(),origin(),
377                     this->shape(),this->strides(),
378                     this->index_bases());
379   }
380
381   reverse_iterator rbegin() {
382     return reverse_iterator(end());
383   }
384
385   reverse_iterator rend() {
386     return reverse_iterator(begin());
387   }
388
389   // Using declarations don't seem to work for g++
390   // These are the proxies to work around this.
391
392   const element* origin() const { return super_type::origin(); }
393
394   template <class IndexList>
395   const element& operator()(const IndexList& indices) const {
396     boost::function_requires<
397       detail::multi_array::CollectionConcept<IndexList> >();
398     return super_type::operator()(indices);
399   }
400
401   const_reference operator[](index idx) const {
402     return super_type::operator[](idx);
403   }
404
405   // see generate_array_view in base.hpp
406 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
407   template <int NDims>
408 #else
409   template <int NumDims, int NDims> // else ICE
410 #endif // BOOST_MSVC
411   typename const_array_view<NDims>::type 
412   operator[](const boost::detail::multi_array::
413              index_gen<NumDims,NDims>& indices)
414     const {
415     return super_type::operator[](indices);
416   }
417   
418   const_iterator begin() const {
419     return super_type::begin();
420   }
421
422   const_iterator end() const {
423     return super_type::end();
424   }
425
426   const_reverse_iterator rbegin() const {
427     return super_type::rbegin();
428   }
429
430   const_reverse_iterator rend() const {
431     return super_type::rend();
432   }
433
434 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
435 private:
436   template <typename,std::size_t> friend class multi_array_impl_base;
437 #else
438 public: // should be private
439 #endif
440
441   // constructor used by multi_array_impl_base::generate_array_view to
442   // generate array views
443   template <typename ExtentList, typename Index>
444   explicit multi_array_view(T* base,
445                             const ExtentList& extents,
446                             const boost::array<Index,NumDims>& strides) :
447     super_type(base,extents,strides) { }
448
449 };
450
451 } // namespace multi_array
452 } // namespace detail
453
454 //
455 // traits classes to get array_view types
456 //
457 template <typename Array, int N>
458 class array_view_gen {
459   typedef typename Array::element element;
460 public:
461   typedef boost::detail::multi_array::multi_array_view<element,N> type;
462 };
463
464 template <typename Array, int N>
465 class const_array_view_gen {
466   typedef typename Array::element element;
467 public:
468   typedef boost::detail::multi_array::const_multi_array_view<element,N> type;  
469 };
470
471 } // namespace boost
472
473 #endif // BOOST_MULTI_ARRAY_VIEW_RG071301_HPP
474