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