1 // Copyright 2002 The Trustees of Indiana University.
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 // Boost.MultiArray Library
8 // Authors: Ronald Garcia
11 // See http://www.boost.org/libs/multi_array for documentation.
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_reverse_iterator const_reverse_iterator
;
48 typedef typename
super_type::element element
;
49 typedef typename
super_type::size_type size_type
;
50 typedef typename
super_type::difference_type difference_type
;
51 typedef typename
super_type::index index
;
52 typedef typename
super_type::extent_range extent_range
;
55 template <std::size_t NDims
>
56 struct const_array_view
{
57 typedef boost::detail::multi_array::const_multi_array_view
<T
,NDims
> type
;
60 template <std::size_t NDims
>
62 typedef boost::detail::multi_array::multi_array_view
<T
,NDims
> type
;
65 // Allow default copy constructor as well.
67 template <typename OPtr
>
68 const_sub_array (const const_sub_array
<T
,NumDims
,OPtr
>& rhs
) :
69 base_(rhs
.base_
), extents_(rhs
.extents_
), strides_(rhs
.strides_
),
70 index_base_(rhs
.index_base_
) {
73 // const_sub_array always returns const types, regardless of its own
75 const_reference
operator[](index idx
) const {
76 return super_type::access(boost::type
<const_reference
>(),
77 idx
,base_
,shape(),strides(),index_bases());
80 template <typename IndexList
>
81 const element
& operator()(const IndexList
& indices
) const {
82 boost::function_requires
<
83 detail::multi_array::CollectionConcept
<IndexList
> >();
84 return super_type::access_element(boost::type
<const element
&>(),
86 shape(),strides(),index_bases());
89 // see generate_array_view in base.hpp
90 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
93 template <int NumDims
, int NDims
> // else ICE
95 typename const_array_view
<NDims
>::type
96 operator[](const boost::detail::multi_array::
97 index_gen
<NumDims
,NDims
>& indices
)
99 typedef typename const_array_view
<NDims
>::type return_type
;
101 super_type::generate_array_view(boost::type
<return_type
>(),
109 template <typename OPtr
>
110 bool operator<(const const_sub_array
<T
,NumDims
,OPtr
>& rhs
) const {
111 return std::lexicographical_compare(begin(),end(),rhs
.begin(),rhs
.end());
114 template <typename OPtr
>
115 bool operator==(const const_sub_array
<T
,NumDims
,OPtr
>& rhs
) const {
116 if(std::equal(shape(),shape()+num_dimensions(),rhs
.shape()))
117 return std::equal(begin(),end(),rhs
.begin());
121 template <typename OPtr
>
122 bool operator!=(const const_sub_array
<T
,NumDims
,OPtr
>& rhs
) const {
123 return !(*this == rhs
);
126 template <typename OPtr
>
127 bool operator>(const const_sub_array
<T
,NumDims
,OPtr
>& rhs
) const {
131 template <typename OPtr
>
132 bool operator<=(const const_sub_array
<T
,NumDims
,OPtr
>& rhs
) const {
133 return !(*this > rhs
);
136 template <typename OPtr
>
137 bool operator>=(const const_sub_array
<T
,NumDims
,OPtr
>& rhs
) const {
138 return !(*this < rhs
);
141 const_iterator
begin() const {
142 return const_iterator(*index_bases(),origin(),
143 shape(),strides(),index_bases());
146 const_iterator
end() const {
147 return const_iterator(*index_bases()+(index
)*shape(),origin(),
148 shape(),strides(),index_bases());
151 const_reverse_iterator
rbegin() const {
152 return const_reverse_iterator(end());
155 const_reverse_iterator
rend() const {
156 return const_reverse_iterator(begin());
159 TPtr
origin() const { return base_
; }
160 size_type
size() const { return extents_
[0]; }
161 size_type
max_size() const { return num_elements(); }
162 bool empty() const { return size() == 0; }
163 size_type
num_dimensions() const { return NumDims
; }
164 const size_type
* shape() const { return extents_
; }
165 const index
* strides() const { return strides_
; }
166 const index
* index_bases() const { return index_base_
; }
168 size_type
num_elements() const {
169 return std::accumulate(shape(),shape() + num_dimensions(),
170 size_type(1), std::multiplies
<size_type
>());
174 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
176 template <typename
,std::size_t> friend class value_accessor_n
;
177 template <typename
,std::size_t,typename
> friend class const_sub_array
;
179 public: // Should be protected
182 const_sub_array (TPtr base
,
183 const size_type
* extents
,
184 const index
* strides
,
185 const index
* index_base
) :
186 base_(base
), extents_(extents
), strides_(strides
),
187 index_base_(index_base
) {
191 const size_type
* extents_
;
192 const index
* strides_
;
193 const index
* index_base_
;
195 // const_sub_array cannot be assigned to (no deep copies!)
196 const_sub_array
& operator=(const const_sub_array
&);
202 // multi_array's proxy class to allow multiple overloads of
203 // operator[] in order to provide a clean multi-dimensional array
205 template <typename T
, std::size_t NumDims
>
206 class sub_array
: public const_sub_array
<T
,NumDims
,T
*>
208 typedef const_sub_array
<T
,NumDims
,T
*> super_type
;
210 typedef typename
super_type::element element
;
211 typedef typename
super_type::reference reference
;
212 typedef typename
super_type::index index
;
213 typedef typename
super_type::size_type size_type
;
214 typedef typename
super_type::iterator iterator
;
215 typedef typename
super_type::reverse_iterator reverse_iterator
;
216 typedef typename
super_type::const_reference const_reference
;
217 typedef typename
super_type::const_iterator const_iterator
;
218 typedef typename
super_type::const_reverse_iterator const_reverse_iterator
;
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 BOOST_ASSERT(other
.num_dimensions() == this->num_dimensions());
239 BOOST_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 BOOST_ASSERT(other
.num_dimensions() == this->num_dimensions());
251 BOOST_ASSERT(std::equal(other
.shape(),
252 other
.shape()+this->num_dimensions(),
254 // iterator-based copy
255 std::copy(other
.begin(),other
.end(),begin());
260 T
* origin() { return this->base_
; }
261 const T
* origin() const { return this->base_
; }
263 reference
operator[](index idx
) {
264 return super_type::access(boost::type
<reference
>(),
265 idx
,this->base_
,this->shape(),this->strides(),
266 this->index_bases());
269 // see generate_array_view in base.hpp
270 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
273 template <int NumDims
, int NDims
> // else ICE
275 typename array_view
<NDims
>::type
276 operator[](const boost::detail::multi_array::
277 index_gen
<NumDims
,NDims
>& indices
) {
278 typedef typename array_view
<NDims
>::type return_type
;
280 super_type::generate_array_view(boost::type
<return_type
>(),
288 template <class IndexList
>
289 element
& operator()(const IndexList
& indices
) {
290 boost::function_requires
<
291 detail::multi_array::CollectionConcept
<IndexList
> >();
292 return super_type::access_element(boost::type
<element
&>(),
294 this->shape(),this->strides(),
295 this->index_bases());
299 return iterator(*this->index_bases(),origin(),
300 this->shape(),this->strides(),this->index_bases());
304 return iterator(*this->index_bases()+(index
)*this->shape(),origin(),
305 this->shape(),this->strides(),this->index_bases());
308 // RG - rbegin() and rend() written naively to thwart MSVC ICE.
309 reverse_iterator
rbegin() {
310 reverse_iterator
ri(end());
314 reverse_iterator
rend() {
315 reverse_iterator
ri(begin());
323 template <class IndexList
>
324 const element
& operator()(const IndexList
& indices
) const {
325 boost::function_requires
<
326 detail::multi_array::CollectionConcept
<IndexList
> >();
327 return super_type::operator()(indices
);
330 const_reference
operator[](index idx
) const {
331 return super_type::operator[](idx
);
334 // see generate_array_view in base.hpp
335 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
338 template <int NumDims
, int NDims
> // else ICE
340 typename const_array_view
<NDims
>::type
341 operator[](const boost::detail::multi_array::
342 index_gen
<NumDims
,NDims
>& indices
)
344 return super_type::operator[](indices
);
347 const_iterator
begin() const {
348 return super_type::begin();
351 const_iterator
end() const {
352 return super_type::end();
355 const_reverse_iterator
rbegin() const {
356 return super_type::rbegin();
359 const_reverse_iterator
rend() const {
360 return super_type::rend();
363 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
365 template <typename
,std::size_t> friend class value_accessor_n
;
367 public: // should be private
371 const size_type
* extents
,
372 const index
* strides
,
373 const index
* index_base
) :
374 super_type(base
,extents
,strides
,index_base
) {
379 } // namespace multi_array
380 } // namespace detail
382 // traits classes to get sub_array types
384 template <typename Array
, int N
>
386 typedef typename
Array::element element
;
388 typedef boost::detail::multi_array::sub_array
<element
,N
> type
;
391 template <typename Array
, int N
>
392 class const_subarray_gen
{
393 typedef typename
Array::element element
;
395 typedef boost::detail::multi_array::const_sub_array
<element
,N
> type
;
399 #endif // SUBARRAY_RG071801_HPP