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