]> git.lyx.org Git - lyx.git/blob - boost/boost/multi_array/view.hpp
Upgrade to boost 1.33.1
[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::detail::multi_array::
77       copy_n(values.begin(),num_dimensions(),index_base_list_.begin());
78     origin_offset_ =
79       this->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       this->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(*index_bases(),origin(),
146                           shape(),strides(),index_bases());
147   }
148
149   const_iterator end() const {
150     return const_iterator(*index_bases()+(index)*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::detail::multi_array::
230       copy_n(extents.begin(),NumDims,extent_list_.begin());
231     boost::detail::multi_array::
232       copy_n(strides.begin(),NumDims,stride_list_.begin());
233
234     // Calculate the array size
235     num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
236                             size_type(1),std::multiplies<size_type>());
237 #if 0
238     assert(num_elements_ != 0);
239 #endif
240   }
241
242   typedef boost::array<size_type,NumDims> size_list;
243   typedef boost::array<index,NumDims> index_list;
244
245   TPtr base_;
246   index origin_offset_;
247   size_type num_elements_;
248   size_list extent_list_;
249   index_list stride_list_;
250   index_list index_base_list_;
251
252 private:
253   // const_multi_array_view cannot be assigned to (no deep copies!)
254   const_multi_array_view& operator=(const const_multi_array_view& other);
255 };
256
257
258 template <typename T, std::size_t NumDims>
259 class multi_array_view :
260   public const_multi_array_view<T,NumDims,T*>
261 {
262   typedef const_multi_array_view<T,NumDims,T*> super_type;
263 public: 
264   typedef typename super_type::value_type value_type;
265   typedef typename super_type::reference reference;
266   typedef typename super_type::iterator iterator;
267   typedef typename super_type::reverse_iterator reverse_iterator;
268   typedef typename super_type::const_reference const_reference;
269   typedef typename super_type::const_iterator const_iterator;
270   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
271   typedef typename super_type::element element;
272   typedef typename super_type::size_type size_type;
273   typedef typename super_type::difference_type difference_type;
274   typedef typename super_type::index index;
275   typedef typename super_type::extent_range extent_range;
276
277   // template typedefs
278   template <std::size_t NDims>
279   struct const_array_view {
280     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
281   };
282
283   template <std::size_t NDims>
284   struct array_view {
285     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
286   };
287
288   // Assignment from other ConstMultiArray types.
289   template <typename ConstMultiArray>
290   multi_array_view& operator=(const ConstMultiArray& other) {
291     function_requires< 
292       boost::detail::multi_array::
293       ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
294
295     // make sure the dimensions agree
296     assert(other.num_dimensions() == this->num_dimensions());
297     assert(std::equal(other.shape(),other.shape()+this->num_dimensions(),
298                       this->shape()));
299     // iterator-based copy
300     std::copy(other.begin(),other.end(),begin());
301     return *this;
302   }
303
304
305   multi_array_view& operator=(const multi_array_view& other) {
306     if (&other != this) {
307       // make sure the dimensions agree
308       assert(other.num_dimensions() == this->num_dimensions());
309       assert(std::equal(other.shape(),other.shape()+this->num_dimensions(),
310                         this->shape()));
311       // iterator-based copy
312       std::copy(other.begin(),other.end(),begin());
313     }
314     return *this;
315   }
316
317   element* origin() { return this->base_+this->origin_offset_; }
318
319   template <class IndexList>
320   element& operator()(const IndexList& indices) {
321     return super_type::access_element(boost::type<element&>(),
322                                       origin(),
323                                       indices,this->strides());
324   }
325
326
327   reference operator[](index idx) {
328     return super_type::access(boost::type<reference>(),
329                               idx,origin(),
330                               this->shape(),this->strides(),
331                               this->index_bases());
332   }
333
334
335   // see generate_array_view in base.hpp
336 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
337   template <int NDims>
338 #else
339   template <int NumDims, int NDims> // else ICE
340 #endif // BOOST_MSVC
341   typename array_view<NDims>::type 
342   operator[](const boost::detail::multi_array::
343              index_gen<NumDims,NDims>& indices) {
344     typedef typename array_view<NDims>::type return_type;
345     return
346       super_type::generate_array_view(boost::type<return_type>(),
347                                       indices,
348                                       this->shape(),
349                                       this->strides(),
350                                       this->index_bases(),
351                                       origin());
352   }
353   
354   
355   iterator begin() {
356     return iterator(*this->index_bases(),origin(),
357                     this->shape(),this->strides(),
358                     this->index_bases());
359   }
360
361   iterator end() {
362     return iterator(*this->index_bases()+(index)*this->shape(),origin(),
363                     this->shape(),this->strides(),
364                     this->index_bases());
365   }
366
367   reverse_iterator rbegin() {
368     return reverse_iterator(end());
369   }
370
371   reverse_iterator rend() {
372     return reverse_iterator(begin());
373   }
374
375   // Using declarations don't seem to work for g++
376   // These are the proxies to work around this.
377
378   const element* origin() const { return super_type::origin(); }
379
380   template <class IndexList>
381   const element& operator()(const IndexList& indices) const {
382     return super_type::operator()(indices);
383   }
384
385   const_reference operator[](index idx) const {
386     return super_type::operator[](idx);
387   }
388
389   // see generate_array_view in base.hpp
390 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
391   template <int NDims>
392 #else
393   template <int NumDims, int NDims> // else ICE
394 #endif // BOOST_MSVC
395   typename const_array_view<NDims>::type 
396   operator[](const boost::detail::multi_array::
397              index_gen<NumDims,NDims>& indices)
398     const {
399     return super_type::operator[](indices);
400   }
401   
402   const_iterator begin() const {
403     return super_type::begin();
404   }
405
406   const_iterator end() const {
407     return super_type::end();
408   }
409
410   const_reverse_iterator rbegin() const {
411     return super_type::rbegin();
412   }
413
414   const_reverse_iterator rend() const {
415     return super_type::rend();
416   }
417
418 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
419 private:
420   template <typename,std::size_t> friend class multi_array_impl_base;
421 #else
422 public: // should be private
423 #endif
424
425   // constructor used by multi_array_impl_base::generate_array_view to
426   // generate array views
427   template <typename ExtentList, typename Index>
428   explicit multi_array_view(T* base,
429                             const ExtentList& extents,
430                             const boost::array<Index,NumDims>& strides) :
431     super_type(base,extents,strides) { }
432
433 };
434
435 } // namespace multi_array
436 } // namespace detail
437
438 //
439 // traits classes to get array_view types
440 //
441 template <typename Array, int N>
442 class array_view_gen {
443   typedef typename Array::element element;
444 public:
445   typedef boost::detail::multi_array::multi_array_view<element,N> type;
446 };
447
448 template <typename Array, int N>
449 class const_array_view_gen {
450   typedef typename Array::element element;
451 public:
452   typedef boost::detail::multi_array::const_multi_array_view<element,N> type;  
453 };
454
455 } // namespace boost
456
457 #endif // BOOST_MULTI_ARRAY_VIEW_RG071301_HPP
458