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