1 #ifndef BOOST_MULTI_ARRAY_REF_RG071801_HPP
2 #define BOOST_MULTI_ARRAY_REF_RG071801_HPP
5 // multi_array_ref.hpp - code for creating "views" of array data.
8 #include "boost/multi_array/base.hpp"
9 #include "boost/multi_array/collection_concept.hpp"
10 #include "boost/multi_array/concept_checks.hpp"
11 #include "boost/multi_array/iterator.hpp"
12 #include "boost/multi_array/storage_order.hpp"
13 #include "boost/multi_array/subarray.hpp"
14 #include "boost/multi_array/view.hpp"
15 #include "boost/multi_array/algorithm.hpp"
16 #include "boost/array.hpp"
17 #include "boost/concept_check.hpp"
18 #include "boost/functional.hpp"
19 #include "boost/limits.hpp"
28 template <typename T, std::size_t NumDims,
29 typename TPtr = const T*
31 class const_multi_array_ref :
32 public detail::multi_array::multi_array_impl_base<T,NumDims>
34 typedef detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
36 typedef typename super_type::value_type value_type;
37 typedef typename super_type::const_reference const_reference;
38 typedef typename super_type::const_iterator const_iterator;
39 typedef typename super_type::const_iter_base const_iter_base;
40 typedef typename super_type::const_reverse_iterator const_reverse_iterator;
41 typedef typename super_type::element element;
42 typedef typename super_type::size_type size_type;
43 typedef typename super_type::difference_type difference_type;
44 typedef typename super_type::index index;
45 typedef typename super_type::extent_range extent_range;
49 template <std::size_t NDims>
50 struct const_array_view {
51 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
54 template <std::size_t NDims>
56 typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
59 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
60 // make const_multi_array_ref a friend of itself
61 template <typename,std::size_t,typename>
62 friend class const_multi_array_ref;
65 template <typename OPtr>
66 const_multi_array_ref(const const_multi_array_ref<T,NumDims,
68 : base_(other.base_), storage_(other.storage_),
69 extent_list_(other.extent_list_),
70 stride_list_(other.stride_list_),
71 index_base_list_(other.index_base_list_),
72 origin_offset_(other.origin_offset_),
73 directional_offset_(other.directional_offset_),
74 num_elements_(other.num_elements_) { }
76 template <typename ExtentList>
77 explicit const_multi_array_ref(TPtr base, const ExtentList& extents) :
78 base_(base), storage_(c_storage_order()) {
79 boost::function_requires<
80 detail::multi_array::CollectionConcept<ExtentList> >();
82 index_base_list_.assign(0);
83 init_multi_array_ref(extents.begin());
86 template <typename ExtentList>
87 explicit const_multi_array_ref(TPtr base, const ExtentList& extents,
88 const general_storage_order<NumDims>& so) :
89 base_(base), storage_(so) {
90 boost::function_requires<
91 detail::multi_array::CollectionConcept<ExtentList> >();
93 index_base_list_.assign(0);
94 init_multi_array_ref(extents.begin());
97 explicit const_multi_array_ref(TPtr base,
98 const detail::multi_array::
99 extent_gen<NumDims>& ranges) :
100 base_(base), storage_(c_storage_order()) {
102 init_from_extent_gen(ranges);
105 explicit const_multi_array_ref(TPtr base,
106 const detail::multi_array::
107 extent_gen<NumDims>& ranges,
108 const general_storage_order<NumDims>& so) :
109 base_(base), storage_(so) {
111 init_from_extent_gen(ranges);
114 template <class InputIterator>
115 void assign(InputIterator begin, InputIterator end) {
116 boost::function_requires<InputIteratorConcept<InputIterator> >();
118 InputIterator in_iter = begin;
120 std::size_t copy_count=0;
121 while (in_iter != end && copy_count < num_elements_) {
122 *out_iter++ = *in_iter++;
127 template <class BaseList>
128 void reindex(const BaseList& values) {
129 boost::function_requires<
130 detail::multi_array::CollectionConcept<BaseList> >();
131 boost::copy_n(values.begin(),num_dimensions(),index_base_list_.begin());
133 calculate_origin_offset(stride_list_,extent_list_,
134 storage_,index_base_list_);
137 void reindex(index value) {
138 index_base_list_.assign(value);
140 calculate_origin_offset(stride_list_,extent_list_,
141 storage_,index_base_list_);
144 template <typename SizeList>
145 void reshape(const SizeList& extents) {
146 boost::function_requires<
147 detail::multi_array::CollectionConcept<SizeList> >();
148 assert(num_elements_ ==
149 std::accumulate(extents.begin(),extents.end(),
150 size_type(1),std::multiplies<size_type>()));
152 std::copy(extents.begin(),extents.end(),extent_list_.begin());
153 compute_strides(stride_list_,extent_list_,storage_);
156 calculate_origin_offset(stride_list_,extent_list_,
157 storage_,index_base_list_);
160 size_type num_dimensions() const { return NumDims; }
162 size_type size() const { return extent_list_.front(); }
164 // given reshaping functionality, this is the max possible size.
165 size_type max_size() const { return num_elements(); }
167 bool empty() const { return size() == 0; }
169 const size_type* shape() const {
170 return extent_list_.data();
173 const index* strides() const {
174 return stride_list_.data();
177 const element* origin() const { return base_+origin_offset_; }
178 const element* data() const { return base_; }
180 size_type num_elements() const { return num_elements_; }
182 const index* index_bases() const {
183 return index_base_list_.data();
186 template <typename IndexList>
187 const element& operator()(IndexList indices) const {
188 boost::function_requires<
189 detail::multi_array::CollectionConcept<IndexList> >();
190 return super_type::access_element(boost::type<const element&>(),
195 // Only allow const element access
196 const_reference operator[](index idx) const {
197 return super_type::access(boost::type<const_reference>(),
199 shape(),strides(),index_bases());
202 // see generate_array_view in base.hpp
206 template <int NumDims, int NDims> // else ICE
208 typename const_array_view<NDims>::type
209 operator[](const detail::multi_array::
210 index_gen<NumDims,NDims>& indices)
212 typedef const_array_view<NDims>::type return_type;
214 super_type::generate_array_view(boost::type<return_type>(),
222 const_iterator begin() const {
223 return const_iterator(const_iter_base(*index_bases(),origin(),
224 shape(),strides(),index_bases()));
227 const_iterator end() const {
228 return const_iterator(const_iter_base(*index_bases()+*shape(),origin(),
229 shape(),strides(),index_bases()));
232 const_reverse_iterator rbegin() const {
233 return const_reverse_iterator(end());
236 const_reverse_iterator rend() const {
237 return const_reverse_iterator(begin());
241 template <typename OPtr>
242 bool operator==(const
243 const_multi_array_ref<T,NumDims,OPtr>& rhs)
245 if(std::equal(extent_list_.begin(),
247 rhs.extent_list_.begin()))
248 return std::equal(begin(),end(),rhs.begin());
252 template <typename OPtr>
254 const_multi_array_ref<T,NumDims,OPtr>& rhs)
256 return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
259 template <typename OPtr>
260 bool operator!=(const
261 const_multi_array_ref<T,NumDims,OPtr>& rhs)
263 return !(*this == rhs);
266 template <typename OPtr>
268 const_multi_array_ref<T,NumDims,OPtr>& rhs)
273 template <typename OPtr>
274 bool operator<=(const
275 const_multi_array_ref<T,NumDims,OPtr>& rhs)
277 return !(*this > rhs);
280 template <typename OPtr>
281 bool operator>=(const
282 const_multi_array_ref<T,NumDims,OPtr>& rhs)
284 return !(*this < rhs);
287 // This ensures that const_multi_array_ref types with different TPtr
288 // types can convert to each other
289 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
294 // This is used by multi_array, which is a subclass of this
295 void set_base_ptr(TPtr new_base) { base_ = new_base; }
297 template <typename OPtr>
298 const_multi_array_ref(const detail::multi_array::
299 const_sub_array<T,NumDims,OPtr>& rhs)
300 : base_(rhs.origin()),
301 storage_(c_storage_order()),
302 origin_offset_(0), directional_offset_(0),
303 num_elements_(rhs.num_elements())
306 copy_n(rhs.shape(),rhs.num_dimensions(),extent_list_.begin());
307 copy_n(rhs.strides(),rhs.num_dimensions(),stride_list_.begin());
308 copy_n(rhs.index_bases(),rhs.num_dimensions(),index_base_list_.begin());
311 typedef boost::array<size_type,NumDims> size_list;
312 typedef boost::array<index,NumDims> index_list;
315 general_storage_order<NumDims> storage_;
316 size_list extent_list_;
317 index_list stride_list_;
318 index_list index_base_list_;
319 index origin_offset_;
320 index directional_offset_;
321 size_type num_elements_;
324 // const_multi_array_ref cannot be assigned to (no deep copies!)
325 const_multi_array_ref& operator=(const const_multi_array_ref& other);
327 void init_from_extent_gen(const
328 detail::multi_array::
329 extent_gen<NumDims>& ranges) {
331 typedef boost::array<index,NumDims> extent_list;
333 // get the index_base values
334 std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
335 index_base_list_.begin(),
336 boost::mem_fun_ref(&extent_range::start));
338 // calculate the extents
340 std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
342 boost::mem_fun_ref(&extent_range::size));
344 init_multi_array_ref(extents.begin());
348 template <class InputIterator>
349 void init_multi_array_ref(InputIterator extents_iter) {
350 boost::function_requires<InputIteratorConcept<InputIterator> >();
352 boost::copy_n(extents_iter,num_dimensions(),extent_list_.begin());
354 // Calculate the array size
355 num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
356 1,std::multiplies<index>());
357 assert(num_elements_ != 0);
359 compute_strides(stride_list_,extent_list_,storage_);
362 calculate_origin_offset(stride_list_,extent_list_,
363 storage_,index_base_list_);
364 directional_offset_ =
365 calculate_descending_dimension_offset(stride_list_,extent_list_,
371 template <typename T, std::size_t NumDims>
372 class multi_array_ref :
373 public const_multi_array_ref<T,NumDims,T*>
375 typedef const_multi_array_ref<T,NumDims,T*> super_type;
377 typedef typename super_type::value_type value_type;
378 typedef typename super_type::reference reference;
379 typedef typename super_type::iterator iterator;
380 typedef typename super_type::iter_base iter_base;
381 typedef typename super_type::reverse_iterator reverse_iterator;
382 typedef typename super_type::const_reference const_reference;
383 typedef typename super_type::const_iterator const_iterator;
384 typedef typename super_type::const_iter_base const_iter_base;
385 typedef typename super_type::const_reverse_iterator const_reverse_iterator;
386 typedef typename super_type::element element;
387 typedef typename super_type::size_type size_type;
388 typedef typename super_type::difference_type difference_type;
389 typedef typename super_type::index index;
390 typedef typename super_type::extent_range extent_range;
394 template <std::size_t NDims>
395 struct const_array_view {
396 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
399 template <std::size_t NDims>
401 typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
404 template <class ExtentList>
405 explicit multi_array_ref(T* base, const ExtentList& extents) :
406 super_type(base,extents) {
407 boost::function_requires<
408 detail::multi_array::CollectionConcept<ExtentList> >();
411 template <class ExtentList>
412 explicit multi_array_ref(T* base, const ExtentList& extents,
413 const general_storage_order<NumDims>& so) :
414 super_type(base,extents,so) {
415 boost::function_requires<
416 detail::multi_array::CollectionConcept<ExtentList> >();
420 explicit multi_array_ref(T* base,
421 const detail::multi_array::
422 extent_gen<NumDims>& ranges) :
423 super_type(base,ranges) { }
426 explicit multi_array_ref(T* base,
427 const detail::multi_array::
430 const general_storage_order<NumDims>& so) :
431 super_type(base,ranges,so) { }
433 template <typename OPtr>
434 multi_array_ref(const detail::multi_array::
435 const_sub_array<T,NumDims,OPtr>& rhs)
438 // Assignment from other ConstMultiArray types.
439 template <typename ConstMultiArray>
440 multi_array_ref& operator=(const ConstMultiArray& other) {
442 detail::multi_array::
443 ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
445 // make sure the dimensions agree
446 assert(other.num_dimensions() == num_dimensions());
447 assert(std::equal(other.shape(),other.shape()+num_dimensions(),
449 // iterator-based copy
450 std::copy(other.begin(),other.end(),begin());
454 multi_array_ref& operator=(const multi_array_ref& other) {
455 if (&other != this) {
456 // make sure the dimensions agree
458 assert(other.num_dimensions() == num_dimensions());
459 assert(std::equal(other.shape(),other.shape()+num_dimensions(),
461 // iterator-based copy
462 std::copy(other.begin(),other.end(),begin());
467 element* origin() { return base_+origin_offset_; }
469 element* data() { return base_; }
471 template <class IndexList>
472 element& operator()(const IndexList& indices) {
473 boost::function_requires<
474 detail::multi_array::CollectionConcept<IndexList> >();
475 return super_type::access_element(boost::type<element&>(),
481 reference operator[](index idx) {
482 return super_type::access(boost::type<reference>(),
489 // See note attached to generate_array_view in base.hpp
493 template <int NumDims, int NDims> // else ICE
495 typename array_view<NDims>::type
496 operator[](const detail::multi_array::
497 index_gen<NumDims,NDims>& indices) {
498 typedef array_view<NDims>::type return_type;
500 super_type::generate_array_view(boost::type<return_type>(),
510 return iterator(iter_base(*index_bases(),origin(),shape(),
511 strides(),index_bases()));
515 return iterator(iter_base(*index_bases()+*shape(),origin(),
516 shape(),strides(),index_bases()));
519 // RG - rbegin() and rend() written naively to thwart MSVC ICE.
520 reverse_iterator rbegin() {
521 reverse_iterator ri(end());
525 reverse_iterator rend() {
526 reverse_iterator ri(begin());
530 // Using declarations don't seem to work for g++
531 // These are the proxies to work around this.
533 const element* origin() const { return super_type::origin(); }
534 const element* data() const { return super_type::data(); }
536 template <class IndexList>
537 const element& operator()(const IndexList& indices) const {
538 boost::function_requires<
539 detail::multi_array::CollectionConcept<IndexList> >();
540 return super_type::operator()(indices);
543 const_reference operator[](index idx) const {
544 return super_type::access(boost::type<const_reference>(),
546 shape(),strides(),index_bases());
549 // See note attached to generate_array_view in base.hpp
553 template <int NumDims, int NDims> // else ICE
555 typename const_array_view<NDims>::type
556 operator[](const detail::multi_array::
557 index_gen<NumDims,NDims>& indices)
559 return super_type::operator[](indices);
562 const_iterator begin() const {
563 return super_type::begin();
566 const_iterator end() const {
567 return super_type::end();
570 const_reverse_iterator rbegin() const {
571 return super_type::rbegin();
574 const_reverse_iterator rend() const {
575 return super_type::rend();
581 #endif // BOOST_MULTI_ARRAY_REF_RG071801_HPP