• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_HPP
14 #define BOOST_MULTI_ARRAY_VIEW_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/type_traits/is_integral.hpp"
27 #include "boost/utility/enable_if.hpp"
28 #include "boost/array.hpp"
29 #include "boost/limits.hpp"
30 #include <algorithm>
31 #include <cstddef>
32 #include <functional>
33 #include <numeric>
34 
35 namespace boost {
36 namespace detail {
37 namespace multi_array {
38 
39 // TPtr = const T* defaulted in base.hpp
40 template <typename T, std::size_t NumDims, typename TPtr>
41 class const_multi_array_view :
42     public boost::detail::multi_array::multi_array_impl_base<T,NumDims>
43 {
44   typedef boost::detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
45 public:
46   typedef typename super_type::value_type value_type;
47   typedef typename super_type::const_reference const_reference;
48   typedef typename super_type::const_iterator const_iterator;
49   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
50   typedef typename super_type::element element;
51   typedef typename super_type::size_type size_type;
52   typedef typename super_type::difference_type difference_type;
53   typedef typename super_type::index index;
54   typedef typename super_type::extent_range extent_range;
55 
56   // template typedefs
57   template <std::size_t NDims>
58   struct const_array_view {
59     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
60   };
61 
62   template <std::size_t NDims>
63   struct array_view {
64     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
65   };
66 
67   template <typename OPtr>
const_multi_array_view(const const_multi_array_view<T,NumDims,OPtr> & other)68   const_multi_array_view(const
69                          const_multi_array_view<T,NumDims,OPtr>& other) :
70     base_(other.base_), origin_offset_(other.origin_offset_),
71     num_elements_(other.num_elements_), extent_list_(other.extent_list_),
72     stride_list_(other.stride_list_), index_base_list_(other.index_base_list_)
73   { }
74 
75 
76   template <class BaseList>
77 #ifdef BOOST_NO_SFINAE
78   void
79 #else
80   typename
81   disable_if<typename boost::is_integral<BaseList>::type,void >::type
82 #endif
reindex(const BaseList & values)83   reindex(const BaseList& values) {
84     boost::function_requires<
85       CollectionConcept<BaseList> >();
86     boost::detail::multi_array::
87       copy_n(values.begin(),num_dimensions(),index_base_list_.begin());
88     origin_offset_ =
89       this->calculate_indexing_offset(stride_list_,index_base_list_);
90   }
91 
reindex(index value)92   void reindex(index value) {
93     index_base_list_.assign(value);
94     origin_offset_ =
95       this->calculate_indexing_offset(stride_list_,index_base_list_);
96   }
97 
num_dimensions() const98   size_type num_dimensions() const { return NumDims; }
99 
size() const100   size_type size() const { return extent_list_.front(); }
max_size() const101   size_type max_size() const { return num_elements(); }
empty() const102   bool empty() const { return size() == 0; }
103 
shape() const104   const size_type* shape() const {
105     return extent_list_.data();
106   }
107 
strides() const108   const index* strides() const {
109     return stride_list_.data();
110   }
111 
origin() const112   const T* origin() const { return base_+origin_offset_; }
113 
num_elements() const114   size_type num_elements() const { return num_elements_; }
115 
index_bases() const116   const index* index_bases() const {
117     return index_base_list_.data();
118   }
119 
120   template <typename IndexList>
operator ()(IndexList indices) const121   const element& operator()(IndexList indices) const {
122     boost::function_requires<
123       CollectionConcept<IndexList> >();
124     return super_type::access_element(boost::type<const element&>(),
125                                       indices,origin(),
126                                       shape(),strides(),index_bases());
127   }
128 
129   // Only allow const element access
operator [](index idx) const130   const_reference operator[](index idx) const {
131     return super_type::access(boost::type<const_reference>(),
132                               idx,origin(),
133                               shape(),strides(),
134                               index_bases());
135   }
136 
137   // see generate_array_view in base.hpp
138   template <int NDims>
139   typename const_array_view<NDims>::type
operator [](const boost::detail::multi_array::index_gen<NumDims,NDims> & indices) const140   operator[](const boost::detail::multi_array::
141              index_gen<NumDims,NDims>& indices)
142     const {
143     typedef typename const_array_view<NDims>::type return_type;
144     return
145       super_type::generate_array_view(boost::type<return_type>(),
146                                       indices,
147                                       shape(),
148                                       strides(),
149                                       index_bases(),
150                                       origin());
151   }
begin() const152   const_iterator begin() const {
153     return const_iterator(*index_bases(),origin(),
154                           shape(),strides(),index_bases());
155   }
156 
end() const157   const_iterator end() const {
158     return const_iterator(*index_bases()+(index)*shape(),origin(),
159                           shape(),strides(),index_bases());
160   }
161 
rbegin() const162   const_reverse_iterator rbegin() const {
163     return const_reverse_iterator(end());
164   }
165 
rend() const166   const_reverse_iterator rend() const {
167     return const_reverse_iterator(begin());
168   }
169 
170 
171   template <typename OPtr>
operator ==(const const_multi_array_view<T,NumDims,OPtr> & rhs) const172   bool operator==(const
173                   const_multi_array_view<T,NumDims,OPtr>& rhs)
174     const {
175     if(std::equal(extent_list_.begin(),
176                   extent_list_.end(),
177                   rhs.extent_list_.begin()))
178       return std::equal(begin(),end(),rhs.begin());
179     else return false;
180   }
181 
182   template <typename OPtr>
operator <(const const_multi_array_view<T,NumDims,OPtr> & rhs) const183   bool operator<(const
184                  const_multi_array_view<T,NumDims,OPtr>& rhs)
185     const {
186     return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
187   }
188 
189   template <typename OPtr>
operator !=(const const_multi_array_view<T,NumDims,OPtr> & rhs) const190   bool operator!=(const
191                   const_multi_array_view<T,NumDims,OPtr>& rhs)
192     const {
193     return !(*this == rhs);
194   }
195 
196   template <typename OPtr>
operator >(const const_multi_array_view<T,NumDims,OPtr> & rhs) const197   bool operator>(const
198                  const_multi_array_view<T,NumDims,OPtr>& rhs)
199     const {
200     return rhs < *this;
201   }
202 
203   template <typename OPtr>
operator <=(const const_multi_array_view<T,NumDims,OPtr> & rhs) const204   bool operator<=(const
205                  const_multi_array_view<T,NumDims,OPtr>& rhs)
206     const {
207     return !(*this > rhs);
208   }
209 
210   template <typename OPtr>
operator >=(const const_multi_array_view<T,NumDims,OPtr> & rhs) const211   bool operator>=(const
212                  const_multi_array_view<T,NumDims,OPtr>& rhs)
213     const {
214     return !(*this < rhs);
215   }
216 
217 
218 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
219 protected:
220   template <typename,std::size_t> friend class multi_array_impl_base;
221   template <typename,std::size_t,typename> friend class const_multi_array_view;
222 #else
223 public: // should be protected
224 #endif
225 
226   // This constructor is used by multi_array_impl_base::generate_array_view
227   // to create strides
228   template <typename ExtentList, typename Index>
const_multi_array_view(TPtr base,const ExtentList & extents,const boost::array<Index,NumDims> & strides)229   explicit const_multi_array_view(TPtr base,
230                            const ExtentList& extents,
231                            const boost::array<Index,NumDims>& strides):
232     base_(base), origin_offset_(0) {
233 
234     index_base_list_.assign(0);
235 
236     // Get the extents and strides
237     boost::detail::multi_array::
238       copy_n(extents.begin(),NumDims,extent_list_.begin());
239     boost::detail::multi_array::
240       copy_n(strides.begin(),NumDims,stride_list_.begin());
241 
242     // Calculate the array size
243     num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
244                                     size_type(1),std::multiplies<size_type>());
245   }
246 
247   typedef boost::array<size_type,NumDims> size_list;
248   typedef boost::array<index,NumDims> index_list;
249 
250   TPtr base_;
251   index origin_offset_;
252   size_type num_elements_;
253   size_list extent_list_;
254   index_list stride_list_;
255   index_list index_base_list_;
256 
257 private:
258   // const_multi_array_view cannot be assigned to (no deep copies!)
259   const_multi_array_view& operator=(const const_multi_array_view& other);
260 };
261 
262 
263 template <typename T, std::size_t NumDims>
264 class multi_array_view :
265   public const_multi_array_view<T,NumDims,T*>
266 {
267   typedef const_multi_array_view<T,NumDims,T*> super_type;
268 public:
269   typedef typename super_type::value_type value_type;
270   typedef typename super_type::reference reference;
271   typedef typename super_type::iterator iterator;
272   typedef typename super_type::reverse_iterator reverse_iterator;
273   typedef typename super_type::const_reference const_reference;
274   typedef typename super_type::const_iterator const_iterator;
275   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
276   typedef typename super_type::element element;
277   typedef typename super_type::size_type size_type;
278   typedef typename super_type::difference_type difference_type;
279   typedef typename super_type::index index;
280   typedef typename super_type::extent_range extent_range;
281 
282   // template typedefs
283   template <std::size_t NDims>
284   struct const_array_view {
285     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
286   };
287 
288   template <std::size_t NDims>
289   struct array_view {
290     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
291   };
292 
293   // Assignment from other ConstMultiArray types.
294   template <typename ConstMultiArray>
operator =(const ConstMultiArray & other)295   multi_array_view& operator=(const ConstMultiArray& other) {
296     function_requires<
297       boost::multi_array_concepts::
298       ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
299 
300     // make sure the dimensions agree
301     BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
302     BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(),
303                             this->shape()));
304     // iterator-based copy
305     std::copy(other.begin(),other.end(),begin());
306     return *this;
307   }
308 
309 
operator =(const multi_array_view & other)310   multi_array_view& operator=(const multi_array_view& other) {
311     if (&other != this) {
312       // make sure the dimensions agree
313       BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
314       BOOST_ASSERT(std::equal(other.shape(),
315                               other.shape()+this->num_dimensions(),
316                               this->shape()));
317       // iterator-based copy
318       std::copy(other.begin(),other.end(),begin());
319     }
320     return *this;
321   }
322 
origin()323   element* origin() { return this->base_+this->origin_offset_; }
324 
325   template <class IndexList>
operator ()(const IndexList & indices)326   element& operator()(const IndexList& indices) {
327     boost::function_requires<
328       CollectionConcept<IndexList> >();
329     return super_type::access_element(boost::type<element&>(),
330                                       indices,origin(),
331                                       this->shape(),this->strides(),
332                                       this->index_bases());
333   }
334 
335 
operator [](index idx)336   reference operator[](index idx) {
337     return super_type::access(boost::type<reference>(),
338                               idx,origin(),
339                               this->shape(),this->strides(),
340                               this->index_bases());
341   }
342 
343 
344   // see generate_array_view in base.hpp
345   template <int NDims>
346   typename array_view<NDims>::type
operator [](const boost::detail::multi_array::index_gen<NumDims,NDims> & indices)347   operator[](const boost::detail::multi_array::
348              index_gen<NumDims,NDims>& indices) {
349     typedef typename array_view<NDims>::type return_type;
350     return
351       super_type::generate_array_view(boost::type<return_type>(),
352                                       indices,
353                                       this->shape(),
354                                       this->strides(),
355                                       this->index_bases(),
356                                       origin());
357   }
358 
359 
begin()360   iterator begin() {
361     return iterator(*this->index_bases(),origin(),
362                     this->shape(),this->strides(),
363                     this->index_bases());
364   }
365 
end()366   iterator end() {
367     return iterator(*this->index_bases()+(index)*this->shape(),origin(),
368                     this->shape(),this->strides(),
369                     this->index_bases());
370   }
371 
rbegin()372   reverse_iterator rbegin() {
373     return reverse_iterator(end());
374   }
375 
rend()376   reverse_iterator rend() {
377     return reverse_iterator(begin());
378   }
379 
380   // Using declarations don't seem to work for g++
381   // These are the proxies to work around this.
382 
origin() const383   const element* origin() const { return super_type::origin(); }
384 
385   template <class IndexList>
operator ()(const IndexList & indices) const386   const element& operator()(const IndexList& indices) const {
387     boost::function_requires<
388       CollectionConcept<IndexList> >();
389     return super_type::operator()(indices);
390   }
391 
operator [](index idx) const392   const_reference operator[](index idx) const {
393     return super_type::operator[](idx);
394   }
395 
396   // see generate_array_view in base.hpp
397   template <int NDims>
398   typename const_array_view<NDims>::type
operator [](const boost::detail::multi_array::index_gen<NumDims,NDims> & indices) const399   operator[](const boost::detail::multi_array::
400              index_gen<NumDims,NDims>& indices)
401     const {
402     return super_type::operator[](indices);
403   }
404 
begin() const405   const_iterator begin() const {
406     return super_type::begin();
407   }
408 
end() const409   const_iterator end() const {
410     return super_type::end();
411   }
412 
rbegin() const413   const_reverse_iterator rbegin() const {
414     return super_type::rbegin();
415   }
416 
rend() const417   const_reverse_iterator rend() const {
418     return super_type::rend();
419   }
420 
421 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
422 private:
423   template <typename,std::size_t> friend class multi_array_impl_base;
424 #else
425 public: // should be private
426 #endif
427 
428   // constructor used by multi_array_impl_base::generate_array_view to
429   // generate array views
430   template <typename ExtentList, typename Index>
multi_array_view(T * base,const ExtentList & extents,const boost::array<Index,NumDims> & strides)431   explicit multi_array_view(T* base,
432                             const ExtentList& extents,
433                             const boost::array<Index,NumDims>& strides) :
434     super_type(base,extents,strides) { }
435 
436 };
437 
438 } // namespace multi_array
439 } // namespace detail
440 
441 //
442 // traits classes to get array_view types
443 //
444 template <typename Array, int N>
445 class array_view_gen {
446   typedef typename Array::element element;
447 public:
448   typedef boost::detail::multi_array::multi_array_view<element,N> type;
449 };
450 
451 template <typename Array, int N>
452 class const_array_view_gen {
453   typedef typename Array::element element;
454 public:
455   typedef boost::detail::multi_array::const_multi_array_view<element,N> type;
456 };
457 
458 } // namespace boost
459 
460 #endif
461