1
// Copyright (C) 2002 Ronald Garcia
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.
9
// This software is provided "as is" without express or implied warranty,
10
// and with no claim as to its suitability for any purpose.
13
#ifndef SUBARRAY_RG071801_HPP
14
#define SUBARRAY_RG071801_HPP
17
// subarray.hpp - used to implement standard operator[] on
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"
31
namespace multi_array {
35
// multi_array's proxy class to allow multiple overloads of
36
// operator[] in order to provide a clean multi-dimensional array
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>
42
typedef boost::detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
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;
56
template <std::size_t NDims>
57
struct const_array_view {
58
typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
61
template <std::size_t NDims>
63
typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
66
// Allow default copy constructor as well.
68
template <typename OPtr>
69
const_sub_array (const const_sub_array<T,NumDims,OPtr>& rhs) :
70
base_(rhs.base_), extents_(rhs.extents_), strides_(rhs.strides_),
71
index_base_(rhs.index_base_) {
74
// const_sub_array always returns const types, regardless of its own
76
const_reference operator[](index idx) const {
77
return super_type::access(boost::type<const_reference>(),
78
idx,base_,shape(),strides(),index_bases());
81
template <typename IndexList>
82
const element& operator()(const IndexList& indices) const {
83
return super_type::access_element(boost::type<const element&>(),
88
// see generate_array_view in base.hpp
89
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
92
template <int NumDims, int NDims> // else ICE
94
typename const_array_view<NDims>::type
95
operator[](const boost::detail::multi_array::
96
index_gen<NumDims,NDims>& indices)
98
typedef typename const_array_view<NDims>::type return_type;
100
super_type::generate_array_view(boost::type<return_type>(),
108
template <typename OPtr>
109
bool operator<(const const_sub_array<T,NumDims,OPtr>& rhs) const {
110
return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
113
template <typename OPtr>
114
bool operator==(const const_sub_array<T,NumDims,OPtr>& rhs) const {
115
if(std::equal(shape(),shape()+num_dimensions(),rhs.shape()))
116
return std::equal(begin(),end(),rhs.begin());
120
template <typename OPtr>
121
bool operator!=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
122
return !(*this == rhs);
125
template <typename OPtr>
126
bool operator>(const const_sub_array<T,NumDims,OPtr>& rhs) const {
130
template <typename OPtr>
131
bool operator<=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
132
return !(*this > rhs);
135
template <typename OPtr>
136
bool operator>=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
137
return !(*this < rhs);
140
const_iterator begin() const {
141
return const_iterator(const_iter_base(*index_bases(),origin(),
142
shape(),strides(),index_bases()));
145
const_iterator end() const {
146
return const_iterator(const_iter_base(*index_bases()+*shape(),origin(),
147
shape(),strides(),index_bases()));
150
const_reverse_iterator rbegin() const {
151
return const_reverse_iterator(end());
154
const_reverse_iterator rend() const {
155
return const_reverse_iterator(begin());
158
TPtr origin() const { return base_; }
159
size_type size() const { return extents_[0]; }
160
size_type max_size() const { return num_elements(); }
161
bool empty() const { return size() == 0; }
162
size_type num_dimensions() const { return NumDims; }
163
const size_type* shape() const { return extents_; }
164
const index* strides() const { return strides_; }
165
const index* index_bases() const { return index_base_; }
167
size_type num_elements() const {
168
return std::accumulate(shape(),shape() + num_dimensions(),
169
size_type(1), std::multiplies<size_type>());
173
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
175
template <typename,std::size_t> friend class value_accessor_n;
176
template <typename,std::size_t,typename> friend class const_sub_array;
178
public: // Should be protected
181
const_sub_array (TPtr base,
182
const size_type* extents,
183
const index* strides,
184
const index* index_base) :
185
base_(base), extents_(extents), strides_(strides),
186
index_base_(index_base) {
190
const size_type* extents_;
191
const index* strides_;
192
const index* index_base_;
194
// const_sub_array cannot be assigned to (no deep copies!)
195
const_sub_array& operator=(const const_sub_array&);
200
// multi_array's proxy class to allow multiple overloads of
201
// operator[] in order to provide a clean multi-dimensional array
203
template <typename T, std::size_t NumDims>
204
class sub_array : public const_sub_array<T,NumDims,T*>
206
typedef const_sub_array<T,NumDims,T*> super_type;
208
typedef typename super_type::element element;
209
typedef typename super_type::reference reference;
210
typedef typename super_type::index index;
211
typedef typename super_type::size_type size_type;
212
typedef typename super_type::iterator iterator;
213
typedef typename super_type::reverse_iterator reverse_iterator;
214
typedef typename super_type::iter_base iter_base;
215
typedef typename super_type::const_reference const_reference;
216
typedef typename super_type::const_iterator const_iterator;
217
typedef typename super_type::const_reverse_iterator const_reverse_iterator;
218
typedef typename super_type::const_iter_base const_iter_base;
221
template <std::size_t NDims>
222
struct const_array_view {
223
typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
226
template <std::size_t NDims>
228
typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
231
// Assignment from other ConstMultiArray types.
232
template <typename ConstMultiArray>
233
sub_array& operator=(const ConstMultiArray& other) {
234
function_requires< boost::detail::multi_array::ConstMultiArrayConcept<
235
ConstMultiArray, NumDims> >();
237
// make sure the dimensions agree
238
assert(other.num_dimensions() == this->num_dimensions());
239
assert(std::equal(other.shape(),other.shape()+this->num_dimensions(),
241
// iterator-based copy
242
std::copy(other.begin(),other.end(),begin());
247
sub_array& operator=(const sub_array& other) {
248
if (&other != this) {
249
// make sure the dimensions agree
250
assert(other.num_dimensions() == this->num_dimensions());
251
assert(std::equal(other.shape(),other.shape()+this->num_dimensions(),
253
// iterator-based copy
254
std::copy(other.begin(),other.end(),begin());
259
T* origin() { return this->base_; }
260
const T* origin() const { return this->base_; }
262
reference operator[](index idx) {
263
return super_type::access(boost::type<reference>(),
264
idx,this->base_,this->shape(),this->strides(),
265
this->index_bases());
268
// see generate_array_view in base.hpp
269
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
272
template <int NumDims, int NDims> // else ICE
274
typename array_view<NDims>::type
275
operator[](const boost::detail::multi_array::
276
index_gen<NumDims,NDims>& indices) {
277
typedef typename array_view<NDims>::type return_type;
279
super_type::generate_array_view(boost::type<return_type>(),
287
template <class IndexList>
288
element& operator()(const IndexList& indices) {
289
return super_type::access_element(boost::type<element&>(),
291
indices,this->strides());
295
return iterator(iter_base(*this->index_bases(),origin(),
296
this->shape(),this->strides(),this->index_bases()));
300
return iterator(iter_base(*this->index_bases()+*this->shape(),origin(),
301
this->shape(),this->strides(),this->index_bases()));
304
// RG - rbegin() and rend() written naively to thwart MSVC ICE.
305
reverse_iterator rbegin() {
306
reverse_iterator ri(end());
310
reverse_iterator rend() {
311
reverse_iterator ri(begin());
319
template <class IndexList>
320
const element& operator()(const IndexList& indices) const {
321
return super_type::operator()(indices);
324
const_reference operator[](index idx) const {
325
return super_type::operator[](idx);
328
// see generate_array_view in base.hpp
329
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
332
template <int NumDims, int NDims> // else ICE
334
typename const_array_view<NDims>::type
335
operator[](const boost::detail::multi_array::
336
index_gen<NumDims,NDims>& indices)
338
return super_type::operator[](indices);
341
const_iterator begin() const {
342
return super_type::begin();
345
const_iterator end() const {
346
return super_type::end();
349
const_reverse_iterator rbegin() const {
350
return super_type::rbegin();
353
const_reverse_iterator rend() const {
354
return super_type::rend();
357
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
359
template <typename,std::size_t> friend class value_accessor_n;
361
public: // should be private
365
const size_type* extents,
366
const index* strides,
367
const index* index_base) :
368
super_type(base,extents,strides,index_base) {
373
} // namespace multi_array
374
} // namespace detail
376
// traits classes to get sub_array types
378
template <typename Array, int N>
380
typedef typename Array::element element;
382
typedef boost::detail::multi_array::sub_array<element,N> type;
385
template <typename Array, int N>
386
class const_subarray_gen {
387
typedef typename Array::element element;
389
typedef boost::detail::multi_array::const_sub_array<element,N> type;
393
#endif // SUBARRAY_RG071801_HPP