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() == num_dimensions());
239 assert(std::equal(other.shape(),other.shape()+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() == num_dimensions());
251 assert(std::equal(other.shape(),other.shape()+num_dimensions(),
253 // iterator-based copy
254 std::copy(other.begin(),other.end(),begin());
259 T* origin() { return base_; }
260 const T* origin() const { return base_; }
262 reference operator[](index idx) {
263 return super_type::access(boost::type<reference>(),
264 idx,base_,shape(),strides(),index_bases());
267 // see generate_array_view in base.hpp
268 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
271 template <int NumDims, int NDims> // else ICE
273 typename array_view<NDims>::type
274 operator[](const boost::detail::multi_array::
275 index_gen<NumDims,NDims>& indices) {
276 typedef typename array_view<NDims>::type return_type;
278 super_type::generate_array_view(boost::type<return_type>(),
286 template <class IndexList>
287 element& operator()(const IndexList& indices) {
288 return super_type::access_element(boost::type<element&>(),
294 return iterator(iter_base(*index_bases(),origin(),
295 shape(),strides(),index_bases()));
299 return iterator(iter_base(*index_bases()+*shape(),origin(),
300 shape(),strides(),index_bases()));
303 // RG - rbegin() and rend() written naively to thwart MSVC ICE.
304 reverse_iterator rbegin() {
305 reverse_iterator ri(end());
309 reverse_iterator rend() {
310 reverse_iterator ri(begin());
318 template <class IndexList>
319 const element& operator()(const IndexList& indices) const {
320 return super_type::operator()(indices);
323 const_reference operator[](index idx) const {
324 return super_type::operator[](idx);
327 // see generate_array_view in base.hpp
328 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
331 template <int NumDims, int NDims> // else ICE
333 typename const_array_view<NDims>::type
334 operator[](const boost::detail::multi_array::
335 index_gen<NumDims,NDims>& indices)
337 return super_type::operator[](indices);
340 const_iterator begin() const {
341 return super_type::begin();
344 const_iterator end() const {
345 return super_type::end();
348 const_reverse_iterator rbegin() const {
349 return super_type::rbegin();
352 const_reverse_iterator rend() const {
353 return super_type::rend();
356 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
358 template <typename,std::size_t> friend class value_accessor_n;
360 public: // should be private
364 const size_type* extents,
365 const index* strides,
366 const index* index_base) :
367 super_type(base,extents,strides,index_base) {
372 } // namespace multi_array
373 } // namespace detail
375 // traits classes to get sub_array types
377 template <typename Array, int N>
379 typedef typename Array::element element;
381 typedef boost::detail::multi_array::sub_array<element,N> type;
384 template <typename Array, int N>
385 class const_subarray_gen {
386 typedef typename Array::element element;
388 typedef boost::detail::multi_array::const_sub_array<element,N> type;
392 #endif // SUBARRAY_RG071801_HPP