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