1 #ifndef BOOST_MULTI_ARRAY_VIEW_RG071301_HPP
2 #define BOOST_MULTI_ARRAY_VIEW_RG071301_HPP
5 // view.hpp - code for creating "views" of array data.
8 #include "boost/multi_array/base.hpp"
9 #include "boost/multi_array/concept_checks.hpp"
10 #include "boost/multi_array/iterator.hpp"
11 #include "boost/multi_array/storage_order.hpp"
12 #include "boost/multi_array/subarray.hpp"
13 #include "boost/multi_array/algorithm.hpp"
14 #include "boost/array.hpp"
15 #include "boost/limits.hpp"
23 namespace multi_array {
25 // TPtr = const T* defaulted in base.hpp
26 template <typename T, std::size_t NumDims, typename TPtr>
27 class const_multi_array_view :
28 public boost::detail::multi_array::multi_array_impl_base<T,NumDims>
30 typedef boost::detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
32 typedef typename super_type::value_type value_type;
33 typedef typename super_type::const_reference const_reference;
34 typedef typename super_type::const_iterator const_iterator;
35 typedef typename super_type::const_iter_base const_iter_base;
36 typedef typename super_type::const_reverse_iterator const_reverse_iterator;
37 typedef typename super_type::element element;
38 typedef typename super_type::size_type size_type;
39 typedef typename super_type::difference_type difference_type;
40 typedef typename super_type::index index;
41 typedef typename super_type::extent_range extent_range;
44 template <std::size_t NDims>
45 struct const_array_view {
46 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
49 template <std::size_t NDims>
51 typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
54 template <typename OPtr>
55 const_multi_array_view(const
56 const_multi_array_view<T,NumDims,OPtr>& other) :
57 base_(other.base_), origin_offset_(other.origin_offset_),
58 num_elements_(other.num_elements_), extent_list_(other.extent_list_),
59 stride_list_(other.stride_list_), index_base_list_(other.index_base_list_)
63 template <class BaseList>
64 void reindex(const BaseList& values) {
65 boost::copy_n(values.begin(),num_dimensions(),index_base_list_.begin());
67 calculate_indexing_offset(stride_list_,index_base_list_);
70 void reindex(index value) {
71 index_base_list_.assign(value);
73 calculate_indexing_offset(stride_list_,index_base_list_);
76 size_type num_dimensions() const { return NumDims; }
78 size_type size() const { return extent_list_.front(); }
79 size_type max_size() const { return num_elements(); }
80 bool empty() const { return size() == 0; }
82 const size_type* shape() const {
83 return extent_list_.data();
86 const index* strides() const {
87 return stride_list_.data();
90 const T* origin() const { return base_+origin_offset_; }
92 size_type num_elements() const { return num_elements_; }
94 const index* index_bases() const {
95 return index_base_list_.data();
98 template <typename IndexList>
99 const element& operator()(IndexList indices) const {
100 return super_type::access_element(boost::type<const element&>(),
105 // Only allow const element access
106 const_reference operator[](index idx) const {
107 return super_type::access(boost::type<const_reference>(),
113 // see generate_array_view in base.hpp
117 template <int NumDims, int NDims> // else ICE
119 typename const_array_view<NDims>::type
120 operator[](const boost::detail::multi_array::
121 index_gen<NumDims,NDims>& indices)
123 typedef const_array_view<NDims>::type return_type;
125 super_type::generate_array_view(boost::type<return_type>(),
132 const_iterator begin() const {
133 return const_iterator(const_iter_base(*index_bases(),origin(),
134 shape(),strides(),index_bases()));
137 const_iterator end() const {
138 return const_iterator(const_iter_base(*index_bases()+*shape(),origin(),
139 shape(),strides(),index_bases()));
142 const_reverse_iterator rbegin() const {
143 return const_reverse_iterator(end());
146 const_reverse_iterator rend() const {
147 return const_reverse_iterator(begin());
151 template <typename OPtr>
152 bool operator==(const
153 const_multi_array_view<T,NumDims,OPtr>& rhs)
155 if(std::equal(extent_list_.begin(),
157 rhs.extent_list_.begin()))
158 return std::equal(begin(),end(),rhs.begin());
162 template <typename OPtr>
164 const_multi_array_view<T,NumDims,OPtr>& rhs)
166 return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
169 template <typename OPtr>
170 bool operator!=(const
171 const_multi_array_view<T,NumDims,OPtr>& rhs)
173 return !(*this == rhs);
176 template <typename OPtr>
178 const_multi_array_view<T,NumDims,OPtr>& rhs)
183 template <typename OPtr>
184 bool operator<=(const
185 const_multi_array_view<T,NumDims,OPtr>& rhs)
187 return !(*this > rhs);
190 template <typename OPtr>
191 bool operator>=(const
192 const_multi_array_view<T,NumDims,OPtr>& rhs)
194 return !(*this < rhs);
198 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
200 template <typename,std::size_t> friend class multi_array_impl_base;
201 template <typename,std::size_t,typename> friend class const_multi_array_view;
203 public: // should be protected
206 // This constructor is used by multi_array_impl_base::generate_array_view
208 template <typename ExtentList, typename Index>
209 explicit const_multi_array_view(TPtr base,
210 const ExtentList& extents,
211 const boost::array<Index,NumDims>& strides):
212 base_(base), origin_offset_(0) {
214 index_base_list_.assign(0);
216 // Get the extents and strides
217 boost::copy_n(extents.begin(),NumDims,extent_list_.begin());
218 boost::copy_n(strides.begin(),NumDims,stride_list_.begin());
220 // Calculate the array size
221 num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
222 size_type(1),std::multiplies<size_type>());
223 assert(num_elements_ != 0);
226 typedef boost::array<size_type,NumDims> size_list;
227 typedef boost::array<index,NumDims> index_list;
230 index origin_offset_;
231 size_type num_elements_;
232 size_list extent_list_;
233 index_list stride_list_;
234 index_list index_base_list_;
237 // const_multi_array_view cannot be assigned to (no deep copies!)
238 const_multi_array_view& operator=(const const_multi_array_view& other);
242 template <typename T, std::size_t NumDims>
243 class multi_array_view :
244 public const_multi_array_view<T,NumDims,T*>
246 typedef const_multi_array_view<T,NumDims,T*> super_type;
248 typedef typename super_type::value_type value_type;
249 typedef typename super_type::reference reference;
250 typedef typename super_type::iterator iterator;
251 typedef typename super_type::iter_base iter_base;
252 typedef typename super_type::reverse_iterator reverse_iterator;
253 typedef typename super_type::const_reference const_reference;
254 typedef typename super_type::const_iterator const_iterator;
255 typedef typename super_type::const_iter_base const_iter_base;
256 typedef typename super_type::const_reverse_iterator const_reverse_iterator;
257 typedef typename super_type::element element;
258 typedef typename super_type::size_type size_type;
259 typedef typename super_type::difference_type difference_type;
260 typedef typename super_type::index index;
261 typedef typename super_type::extent_range extent_range;
264 template <std::size_t NDims>
265 struct const_array_view {
266 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
269 template <std::size_t NDims>
271 typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
274 // Assignment from other ConstMultiArray types.
275 template <typename ConstMultiArray>
276 multi_array_view& operator=(const ConstMultiArray& other) {
278 boost::detail::multi_array::
279 ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
281 // make sure the dimensions agree
282 assert(other.num_dimensions() == num_dimensions());
283 assert(std::equal(other.shape(),other.shape()+num_dimensions(),
285 // iterator-based copy
286 std::copy(other.begin(),other.end(),begin());
291 multi_array_view& operator=(const multi_array_view& other) {
292 if (&other != this) {
293 // make sure the dimensions agree
294 assert(other.num_dimensions() == num_dimensions());
295 assert(std::equal(other.shape(),other.shape()+num_dimensions(),
297 // iterator-based copy
298 std::copy(other.begin(),other.end(),begin());
303 element* origin() { return base_+origin_offset_; }
305 template <class IndexList>
306 element& operator()(const IndexList& indices) {
307 return super_type::access_element(boost::type<element&>(),
313 reference operator[](index idx) {
314 return super_type::access(boost::type<reference>(),
321 // see generate_array_view in base.hpp
325 template <int NumDims, int NDims> // else ICE
327 typename array_view<NDims>::type
328 operator[](const boost::detail::multi_array::
329 index_gen<NumDims,NDims>& indices) {
330 typedef array_view<NDims>::type return_type;
332 super_type::generate_array_view(boost::type<return_type>(),
342 return iterator(iter_base(*index_bases(),origin(),
343 shape(),strides(),index_bases()));
347 return iterator(iter_base(*index_bases()+*shape(),origin(),
348 shape(),strides(),index_bases()));
351 reverse_iterator rbegin() {
352 return reverse_iterator(end());
355 reverse_iterator rend() {
356 return reverse_iterator(begin());
359 // Using declarations don't seem to work for g++
360 // These are the proxies to work around this.
362 const element* origin() const { return super_type::origin(); }
364 template <class IndexList>
365 const element& operator()(const IndexList& indices) const {
366 return super_type::operator()(indices);
369 const_reference operator[](index idx) const {
370 return super_type::operator[](idx);
373 // see generate_array_view in base.hpp
377 template <int NumDims, int NDims> // else ICE
379 typename const_array_view<NDims>::type
380 operator[](const boost::detail::multi_array::
381 index_gen<NumDims,NDims>& indices)
383 return super_type::operator[](indices);
386 const_iterator begin() const {
387 return super_type::begin();
390 const_iterator end() const {
391 return super_type::end();
394 const_reverse_iterator rbegin() const {
395 return super_type::rbegin();
398 const_reverse_iterator rend() const {
399 return super_type::rend();
402 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
404 template <typename,std::size_t> friend class multi_array_impl_base;
406 public: // should be private
409 // constructor used by multi_array_impl_base::generate_array_view to
410 // generate array views
411 template <typename ExtentList, typename Index>
412 explicit multi_array_view(T* base,
413 const ExtentList& extents,
414 const boost::array<Index,NumDims>& strides) :
415 super_type(base,extents,strides) { }
419 } // namespace multi_array
420 } // namespace detail
423 // traits classes to get array_view types
425 template <typename Array, int N>
426 class array_view_gen {
427 typedef typename Array::element element;
429 typedef boost::detail::multi_array::multi_array_view<element,N> type;
432 template <typename Array, int N>
433 class const_array_view_gen {
434 typedef typename Array::element element;
436 typedef boost::detail::multi_array::const_multi_array_view<element,N> type;
441 #endif // BOOST_MULTI_ARRAY_VIEW_RG071301_HPP