• 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_SUBARRAY_HPP
14 #define BOOST_MULTI_ARRAY_SUBARRAY_HPP
15 
16 //
17 // subarray.hpp - used to implement standard operator[] on
18 // multi_arrays
19 //
20 
21 #include "boost/multi_array/base.hpp"
22 #include "boost/multi_array/concept_checks.hpp"
23 #include "boost/limits.hpp"
24 #include "boost/type.hpp"
25 #include <algorithm>
26 #include <cstddef>
27 #include <functional>
28 
29 namespace boost {
30 namespace detail {
31 namespace multi_array {
32 
33 //
34 // const_sub_array
35 //    multi_array's proxy class to allow multiple overloads of
36 //    operator[] in order to provide a clean multi-dimensional array
37 //    interface.
38 template <typename T, std::size_t NumDims, typename TPtr>
39 class const_sub_array :
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   // Allow default copy constructor as well.
66 
67   template <typename OPtr>
const_sub_array(const const_sub_array<T,NumDims,OPtr> & rhs)68   const_sub_array (const const_sub_array<T,NumDims,OPtr>& rhs) :
69     base_(rhs.base_), extents_(rhs.extents_), strides_(rhs.strides_),
70     index_base_(rhs.index_base_) {
71   }
72 
73   // const_sub_array always returns const types, regardless of its own
74   // constness.
operator [](index idx) const75   const_reference operator[](index idx) const {
76     return super_type::access(boost::type<const_reference>(),
77                               idx,base_,shape(),strides(),index_bases());
78   }
79 
80   template <typename IndexList>
operator ()(const IndexList & indices) const81   const element& operator()(const IndexList& indices) const {
82     boost::function_requires<
83       CollectionConcept<IndexList> >();
84     return super_type::access_element(boost::type<const element&>(),
85                                       indices,origin(),
86                                       shape(),strides(),index_bases());
87   }
88 
89   // see generate_array_view in base.hpp
90   template <int NDims>
91   typename const_array_view<NDims>::type
operator [](const boost::detail::multi_array::index_gen<NumDims,NDims> & indices) const92   operator[](const boost::detail::multi_array::
93              index_gen<NumDims,NDims>& indices)
94     const {
95     typedef typename const_array_view<NDims>::type return_type;
96     return
97       super_type::generate_array_view(boost::type<return_type>(),
98                                       indices,
99                                       shape(),
100                                       strides(),
101                                       index_bases(),
102                                       base_);
103   }
104 
105   template <typename OPtr>
operator <(const const_sub_array<T,NumDims,OPtr> & rhs) const106   bool operator<(const const_sub_array<T,NumDims,OPtr>& rhs) const {
107     return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
108   }
109 
110   template <typename OPtr>
operator ==(const const_sub_array<T,NumDims,OPtr> & rhs) const111   bool operator==(const const_sub_array<T,NumDims,OPtr>& rhs) const {
112     if(std::equal(shape(),shape()+num_dimensions(),rhs.shape()))
113       return std::equal(begin(),end(),rhs.begin());
114     else return false;
115   }
116 
117   template <typename OPtr>
operator !=(const const_sub_array<T,NumDims,OPtr> & rhs) const118   bool operator!=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
119     return !(*this == rhs);
120   }
121 
122   template <typename OPtr>
operator >(const const_sub_array<T,NumDims,OPtr> & rhs) const123   bool operator>(const const_sub_array<T,NumDims,OPtr>& rhs) const {
124     return rhs < *this;
125   }
126 
127   template <typename OPtr>
operator <=(const const_sub_array<T,NumDims,OPtr> & rhs) const128   bool operator<=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
129     return !(*this > rhs);
130   }
131 
132   template <typename OPtr>
operator >=(const const_sub_array<T,NumDims,OPtr> & rhs) const133   bool operator>=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
134     return !(*this < rhs);
135   }
136 
begin() const137   const_iterator begin() const {
138     return const_iterator(*index_bases(),origin(),
139                           shape(),strides(),index_bases());
140   }
141 
end() const142   const_iterator end() const {
143     return const_iterator(*index_bases()+(index)*shape(),origin(),
144                           shape(),strides(),index_bases());
145   }
146 
rbegin() const147   const_reverse_iterator rbegin() const {
148     return const_reverse_iterator(end());
149   }
150 
rend() const151   const_reverse_iterator rend() const {
152     return const_reverse_iterator(begin());
153   }
154 
origin() const155   TPtr origin() const { return base_; }
size() const156   size_type size() const { return extents_[0]; }
max_size() const157   size_type max_size() const { return num_elements(); }
empty() const158   bool empty() const { return size() == 0; }
num_dimensions() const159   size_type num_dimensions() const { return NumDims; }
shape() const160   const size_type*  shape() const { return extents_; }
strides() const161   const index* strides() const { return strides_; }
index_bases() const162   const index* index_bases() const { return index_base_; }
163 
num_elements() const164   size_type num_elements() const {
165     return std::accumulate(shape(),shape() + num_dimensions(),
166                            size_type(1), std::multiplies<size_type>());
167   }
168 
169 
170 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
171 protected:
172   template <typename,std::size_t> friend class value_accessor_n;
173   template <typename,std::size_t,typename> friend class const_sub_array;
174 #else
175 public:  // Should be protected
176 #endif
177 
const_sub_array(TPtr base,const size_type * extents,const index * strides,const index * index_base)178   const_sub_array (TPtr base,
179                  const size_type* extents,
180                  const index* strides,
181                  const index* index_base) :
182     base_(base), extents_(extents), strides_(strides),
183     index_base_(index_base) {
184   }
185 
186   TPtr base_;
187   const size_type* extents_;
188   const index* strides_;
189   const index* index_base_;
190 private:
191   // const_sub_array cannot be assigned to (no deep copies!)
192   const_sub_array& operator=(const const_sub_array&);
193 };
194 
195 
196 //
197 // sub_array
198 //    multi_array's proxy class to allow multiple overloads of
199 //    operator[] in order to provide a clean multi-dimensional array
200 //    interface.
201 template <typename T, std::size_t NumDims>
202 class sub_array : public const_sub_array<T,NumDims,T*>
203 {
204   typedef const_sub_array<T,NumDims,T*> super_type;
205 public:
206   typedef typename super_type::element element;
207   typedef typename super_type::reference reference;
208   typedef typename super_type::index index;
209   typedef typename super_type::size_type size_type;
210   typedef typename super_type::iterator iterator;
211   typedef typename super_type::reverse_iterator reverse_iterator;
212   typedef typename super_type::const_reference const_reference;
213   typedef typename super_type::const_iterator const_iterator;
214   typedef typename super_type::const_reverse_iterator const_reverse_iterator;
215 
216   // template typedefs
217   template <std::size_t NDims>
218   struct const_array_view {
219     typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
220   };
221 
222   template <std::size_t NDims>
223   struct array_view {
224     typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
225   };
226 
227   // Assignment from other ConstMultiArray types.
228   template <typename ConstMultiArray>
operator =(const ConstMultiArray & other)229   sub_array& operator=(const ConstMultiArray& other) {
230     function_requires< boost::multi_array_concepts::ConstMultiArrayConcept<
231         ConstMultiArray, NumDims> >();
232 
233     // make sure the dimensions agree
234     BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
235     BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(),
236                             this->shape()));
237     // iterator-based copy
238     std::copy(other.begin(),other.end(),begin());
239     return *this;
240   }
241 
242 
operator =(const sub_array & other)243   sub_array& operator=(const sub_array& other) {
244     if (&other != this) {
245       // make sure the dimensions agree
246       BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
247       BOOST_ASSERT(std::equal(other.shape(),
248                               other.shape()+this->num_dimensions(),
249                               this->shape()));
250       // iterator-based copy
251       std::copy(other.begin(),other.end(),begin());
252     }
253     return *this;
254   }
255 
origin()256   T* origin() { return this->base_; }
origin() const257   const T* origin() const { return this->base_; }
258 
operator [](index idx)259   reference operator[](index idx) {
260     return super_type::access(boost::type<reference>(),
261                               idx,this->base_,this->shape(),this->strides(),
262                               this->index_bases());
263   }
264 
265   // see generate_array_view in base.hpp
266   template <int NDims>
267   typename array_view<NDims>::type
operator [](const boost::detail::multi_array::index_gen<NumDims,NDims> & indices)268   operator[](const boost::detail::multi_array::
269              index_gen<NumDims,NDims>& indices) {
270     typedef typename array_view<NDims>::type return_type;
271     return
272       super_type::generate_array_view(boost::type<return_type>(),
273                                       indices,
274                                       this->shape(),
275                                       this->strides(),
276                                       this->index_bases(),
277                                       origin());
278   }
279 
280   template <class IndexList>
operator ()(const IndexList & indices)281   element& operator()(const IndexList& indices) {
282     boost::function_requires<
283       CollectionConcept<IndexList> >();
284     return super_type::access_element(boost::type<element&>(),
285                                       indices,origin(),
286                                       this->shape(),this->strides(),
287                                       this->index_bases());
288   }
289 
begin()290   iterator begin() {
291     return iterator(*this->index_bases(),origin(),
292                     this->shape(),this->strides(),this->index_bases());
293   }
294 
end()295   iterator end() {
296     return iterator(*this->index_bases()+(index)*this->shape(),origin(),
297                     this->shape(),this->strides(),this->index_bases());
298   }
299 
300   // RG - rbegin() and rend() written naively to thwart MSVC ICE.
rbegin()301   reverse_iterator rbegin() {
302     reverse_iterator ri(end());
303     return ri;
304   }
305 
rend()306   reverse_iterator rend() {
307     reverse_iterator ri(begin());
308     return ri;
309   }
310 
311   //
312   // proxies
313   //
314 
315   template <class IndexList>
operator ()(const IndexList & indices) const316   const element& operator()(const IndexList& indices) const {
317     boost::function_requires<
318       CollectionConcept<IndexList> >();
319     return super_type::operator()(indices);
320   }
321 
operator [](index idx) const322   const_reference operator[](index idx) const {
323     return super_type::operator[](idx);
324   }
325 
326   // see generate_array_view in base.hpp
327   template <int NDims>
328   typename const_array_view<NDims>::type
operator [](const boost::detail::multi_array::index_gen<NumDims,NDims> & indices) const329   operator[](const boost::detail::multi_array::
330              index_gen<NumDims,NDims>& indices)
331     const {
332     return super_type::operator[](indices);
333   }
334 
begin() const335   const_iterator begin() const {
336     return super_type::begin();
337   }
338 
end() const339   const_iterator end() const {
340     return super_type::end();
341   }
342 
rbegin() const343   const_reverse_iterator rbegin() const {
344     return super_type::rbegin();
345   }
346 
rend() const347   const_reverse_iterator rend() const {
348     return super_type::rend();
349   }
350 
351 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
352 private:
353   template <typename,std::size_t> friend class value_accessor_n;
354 #else
355 public: // should be private
356 #endif
357 
sub_array(T * base,const size_type * extents,const index * strides,const index * index_base)358   sub_array (T* base,
359             const size_type* extents,
360             const index* strides,
361             const index* index_base) :
362     super_type(base,extents,strides,index_base) {
363   }
364 
365 };
366 
367 } // namespace multi_array
368 } // namespace detail
369 //
370 // traits classes to get sub_array types
371 //
372 template <typename Array, int N>
373 class subarray_gen {
374   typedef typename Array::element element;
375 public:
376   typedef boost::detail::multi_array::sub_array<element,N> type;
377 };
378 
379 template <typename Array, int N>
380 class const_subarray_gen {
381   typedef typename Array::element element;
382 public:
383   typedef boost::detail::multi_array::const_sub_array<element,N> type;
384 };
385 } // namespace boost
386 
387 #endif
388