]> git.lyx.org Git - lyx.git/blob - boost/boost/multi_array/view.hpp
update boost to pre-1.30.0
[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       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(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() == this->num_dimensions());
295     assert(std::equal(other.shape(),other.shape()+this->num_dimensions(),
296                       this->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() == this->num_dimensions());
307       assert(std::equal(other.shape(),other.shape()+this->num_dimensions(),
308                         this->shape()));
309       // iterator-based copy
310       std::copy(other.begin(),other.end(),begin());
311     }
312     return *this;
313   }
314
315   element* origin() { return this->base_+this->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,this->strides());
322   }
323
324
325   reference operator[](index idx) {
326     return super_type::access(boost::type<reference>(),
327                               idx,origin(),
328                               this->shape(),this->strides(),
329                               this->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                                       this->shape(),
347                                       this->strides(),
348                                       this->index_bases(),
349                                       origin());
350   }
351   
352   
353   iterator begin() {
354     return iterator(iter_base(*this->index_bases(),origin(),
355                               this->shape(),this->strides(),
356                               this->index_bases()));
357   }
358
359   iterator end() {
360     return iterator(iter_base(*this->index_bases()+*this->shape(),origin(),
361                               this->shape(),this->strides(),
362                               this->index_bases()));
363   }
364
365   reverse_iterator rbegin() {
366     return reverse_iterator(end());
367   }
368
369   reverse_iterator rend() {
370     return reverse_iterator(begin());
371   }
372
373   // Using declarations don't seem to work for g++
374   // These are the proxies to work around this.
375
376   const element* origin() const { return super_type::origin(); }
377
378   template <class IndexList>
379   const element& operator()(const IndexList& indices) const {
380     return super_type::operator()(indices);
381   }
382
383   const_reference operator[](index idx) const {
384     return super_type::operator[](idx);
385   }
386
387   // see generate_array_view in base.hpp
388 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
389   template <int NDims>
390 #else
391   template <int NumDims, int NDims> // else ICE
392 #endif // BOOST_MSVC
393   typename const_array_view<NDims>::type 
394   operator[](const boost::detail::multi_array::
395              index_gen<NumDims,NDims>& indices)
396     const {
397     return super_type::operator[](indices);
398   }
399   
400   const_iterator begin() const {
401     return super_type::begin();
402   }
403
404   const_iterator end() const {
405     return super_type::end();
406   }
407
408   const_reverse_iterator rbegin() const {
409     return super_type::rbegin();
410   }
411
412   const_reverse_iterator rend() const {
413     return super_type::rend();
414   }
415
416 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
417 private:
418   template <typename,std::size_t> friend class multi_array_impl_base;
419 #else
420 public: // should be private
421 #endif
422
423   // constructor used by multi_array_impl_base::generate_array_view to
424   // generate array views
425   template <typename ExtentList, typename Index>
426   explicit multi_array_view(T* base,
427                             const ExtentList& extents,
428                             const boost::array<Index,NumDims>& strides) :
429     super_type(base,extents,strides) { }
430
431 };
432
433 } // namespace multi_array
434 } // namespace detail
435
436 //
437 // traits classes to get array_view types
438 //
439 template <typename Array, int N>
440 class array_view_gen {
441   typedef typename Array::element element;
442 public:
443   typedef boost::detail::multi_array::multi_array_view<element,N> type;
444 };
445
446 template <typename Array, int N>
447 class const_array_view_gen {
448   typedef typename Array::element element;
449 public:
450   typedef boost::detail::multi_array::const_multi_array_view<element,N> type;  
451 };
452
453 } // namespace boost
454
455 #endif // BOOST_MULTI_ARRAY_VIEW_RG071301_HPP
456