1 // Copyright 2002 The Trustees of Indiana University. 2 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) 6 7 // Boost.MultiArray Library 8 // Authors: Ronald Garcia 9 // Jeremy Siek 10 // Andrew Lumsdaine 11 // See http://www.boost.org/libs/multi_array for documentation. 12 13 #ifndef SUBARRAY_RG071801_HPP 14 #define SUBARRAY_RG071801_HPP 15 16 // 17 // subarray.hpp - used to implement standard operator[] on 18 // multi_arrays 19 // 20 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" 25 #include <algorithm> 26 #include <cstddef> 27 #include <functional> 28 29 namespace boost { 30 namespace detail { 31 namespace multi_array { 32 33 // 34 // const_sub_array 35 // multi_array's proxy class to allow multiple overloads of 36 // operator[] in order to provide a clean multi-dimensional array 37 // interface. 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> 41 { 42 typedef boost::detail::multi_array::multi_array_impl_base<T,NumDims> super_type; 43 public: 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; 53 54 // template typedefs 55 template <std::size_t NDims> 56 struct const_array_view { 57 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type; 58 }; 59 60 template <std::size_t NDims> 61 struct array_view { 62 typedef boost::detail::multi_array::multi_array_view<T,NDims> type; 63 }; 64 65 // Allow default copy constructor as well. 66 67 template <typename OPtr> const_sub_array(const const_sub_array<T,NumDims,OPtr> & rhs)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_) { 71 } 72 73 // const_sub_array always returns const types, regardless of its own 74 // constness. operator [](index idx) const75 const_reference operator[](index idx) const { 76 return super_type::access(boost::type<const_reference>(), 77 idx,base_,shape(),strides(),index_bases()); 78 } 79 80 template <typename IndexList> operator ()(const IndexList & indices) const81 const element& operator()(const IndexList& indices) const { 82 return super_type::access_element(boost::type<const element&>(), 83 origin(), 84 indices,strides()); 85 } 86 87 // see generate_array_view in base.hpp 88 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 89 template <int NDims> 90 #else 91 template <int NumDims, int NDims> // else ICE 92 #endif // BOOST_MSVC 93 typename const_array_view<NDims>::type operator [](const boost::detail::multi_array::index_gen<NumDims,NDims> & indices) const94 operator[](const boost::detail::multi_array:: 95 index_gen<NumDims,NDims>& indices) 96 const { 97 typedef typename const_array_view<NDims>::type return_type; 98 return 99 super_type::generate_array_view(boost::type<return_type>(), 100 indices, 101 shape(), 102 strides(), 103 index_bases(), 104 base_); 105 } 106 107 template <typename OPtr> operator <(const const_sub_array<T,NumDims,OPtr> & rhs) const108 bool operator<(const const_sub_array<T,NumDims,OPtr>& rhs) const { 109 return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end()); 110 } 111 112 template <typename OPtr> operator ==(const const_sub_array<T,NumDims,OPtr> & rhs) const113 bool operator==(const const_sub_array<T,NumDims,OPtr>& rhs) const { 114 if(std::equal(shape(),shape()+num_dimensions(),rhs.shape())) 115 return std::equal(begin(),end(),rhs.begin()); 116 else return false; 117 } 118 119 template <typename OPtr> operator !=(const const_sub_array<T,NumDims,OPtr> & rhs) const120 bool operator!=(const const_sub_array<T,NumDims,OPtr>& rhs) const { 121 return !(*this == rhs); 122 } 123 124 template <typename OPtr> operator >(const const_sub_array<T,NumDims,OPtr> & rhs) const125 bool operator>(const const_sub_array<T,NumDims,OPtr>& rhs) const { 126 return rhs < *this; 127 } 128 129 template <typename OPtr> operator <=(const const_sub_array<T,NumDims,OPtr> & rhs) const130 bool operator<=(const const_sub_array<T,NumDims,OPtr>& rhs) const { 131 return !(*this > rhs); 132 } 133 134 template <typename OPtr> operator >=(const const_sub_array<T,NumDims,OPtr> & rhs) const135 bool operator>=(const const_sub_array<T,NumDims,OPtr>& rhs) const { 136 return !(*this < rhs); 137 } 138 begin() const139 const_iterator begin() const { 140 return const_iterator(*index_bases(),origin(), 141 shape(),strides(),index_bases()); 142 } 143 end() const144 const_iterator end() const { 145 return const_iterator(*index_bases()+(index)*shape(),origin(), 146 shape(),strides(),index_bases()); 147 } 148 rbegin() const149 const_reverse_iterator rbegin() const { 150 return const_reverse_iterator(end()); 151 } 152 rend() const153 const_reverse_iterator rend() const { 154 return const_reverse_iterator(begin()); 155 } 156 origin() const157 TPtr origin() const { return base_; } size() const158 size_type size() const { return extents_[0]; } max_size() const159 size_type max_size() const { return num_elements(); } empty() const160 bool empty() const { return size() == 0; } num_dimensions() const161 size_type num_dimensions() const { return NumDims; } shape() const162 const size_type* shape() const { return extents_; } strides() const163 const index* strides() const { return strides_; } index_bases() const164 const index* index_bases() const { return index_base_; } 165 num_elements() const166 size_type num_elements() const { 167 return std::accumulate(shape(),shape() + num_dimensions(), 168 size_type(1), std::multiplies<size_type>()); 169 } 170 171 172 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS 173 protected: 174 template <typename,std::size_t> friend class value_accessor_n; 175 template <typename,std::size_t,typename> friend class const_sub_array; 176 #else 177 public: // Should be protected 178 #endif 179 const_sub_array(TPtr base,const size_type * extents,const index * strides,const index * index_base)180 const_sub_array (TPtr base, 181 const size_type* extents, 182 const index* strides, 183 const index* index_base) : 184 base_(base), extents_(extents), strides_(strides), 185 index_base_(index_base) { 186 } 187 188 TPtr base_; 189 const size_type* extents_; 190 const index* strides_; 191 const index* index_base_; 192 private: 193 // const_sub_array cannot be assigned to (no deep copies!) 194 const_sub_array& operator=(const const_sub_array&); 195 }; 196 197 198 // 199 // sub_array 200 // multi_array's proxy class to allow multiple overloads of 201 // operator[] in order to provide a clean multi-dimensional array 202 // interface. 203 template <typename T, std::size_t NumDims> 204 class sub_array : public const_sub_array<T,NumDims,T*> 205 { 206 typedef const_sub_array<T,NumDims,T*> super_type; 207 public: 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::const_reference const_reference; 215 typedef typename super_type::const_iterator const_iterator; 216 typedef typename super_type::const_reverse_iterator const_reverse_iterator; 217 218 // template typedefs 219 template <std::size_t NDims> 220 struct const_array_view { 221 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type; 222 }; 223 224 template <std::size_t NDims> 225 struct array_view { 226 typedef boost::detail::multi_array::multi_array_view<T,NDims> type; 227 }; 228 229 // Assignment from other ConstMultiArray types. 230 template <typename ConstMultiArray> operator =(const ConstMultiArray & other)231 sub_array& operator=(const ConstMultiArray& other) { 232 function_requires< boost::detail::multi_array::ConstMultiArrayConcept< 233 ConstMultiArray, NumDims> >(); 234 235 // make sure the dimensions agree 236 assert(other.num_dimensions() == this->num_dimensions()); 237 assert(std::equal(other.shape(),other.shape()+this->num_dimensions(), 238 this->shape())); 239 // iterator-based copy 240 std::copy(other.begin(),other.end(),begin()); 241 return *this; 242 } 243 244 operator =(const sub_array & other)245 sub_array& operator=(const sub_array& other) { 246 if (&other != this) { 247 // make sure the dimensions agree 248 assert(other.num_dimensions() == this->num_dimensions()); 249 assert(std::equal(other.shape(),other.shape()+this->num_dimensions(), 250 this->shape())); 251 // iterator-based copy 252 std::copy(other.begin(),other.end(),begin()); 253 } 254 return *this; 255 } 256 origin()257 T* origin() { return this->base_; } origin() const258 const T* origin() const { return this->base_; } 259 operator [](index idx)260 reference operator[](index idx) { 261 return super_type::access(boost::type<reference>(), 262 idx,this->base_,this->shape(),this->strides(), 263 this->index_bases()); 264 } 265 266 // see generate_array_view in base.hpp 267 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 268 template <int NDims> 269 #else 270 template <int NumDims, int NDims> // else ICE 271 #endif // BOOST_MSVC 272 typename array_view<NDims>::type operator [](const boost::detail::multi_array::index_gen<NumDims,NDims> & indices)273 operator[](const boost::detail::multi_array:: 274 index_gen<NumDims,NDims>& indices) { 275 typedef typename array_view<NDims>::type return_type; 276 return 277 super_type::generate_array_view(boost::type<return_type>(), 278 indices, 279 this->shape(), 280 this->strides(), 281 this->index_bases(), 282 origin()); 283 } 284 285 template <class IndexList> operator ()(const IndexList & indices)286 element& operator()(const IndexList& indices) { 287 return super_type::access_element(boost::type<element&>(), 288 origin(), 289 indices,this->strides()); 290 } 291 begin()292 iterator begin() { 293 return iterator(*this->index_bases(),origin(), 294 this->shape(),this->strides(),this->index_bases()); 295 } 296 end()297 iterator end() { 298 return iterator(*this->index_bases()+(index)*this->shape(),origin(), 299 this->shape(),this->strides(),this->index_bases()); 300 } 301 302 // RG - rbegin() and rend() written naively to thwart MSVC ICE. rbegin()303 reverse_iterator rbegin() { 304 reverse_iterator ri(end()); 305 return ri; 306 } 307 rend()308 reverse_iterator rend() { 309 reverse_iterator ri(begin()); 310 return ri; 311 } 312 313 // 314 // proxies 315 // 316 317 template <class IndexList> operator ()(const IndexList & indices) const318 const element& operator()(const IndexList& indices) const { 319 return super_type::operator()(indices); 320 } 321 operator [](index idx) const322 const_reference operator[](index idx) const { 323 return super_type::operator[](idx); 324 } 325 326 // see generate_array_view in base.hpp 327 #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 328 template <int NDims> 329 #else 330 template <int NumDims, int NDims> // else ICE 331 #endif // BOOST_MSVC 332 typename const_array_view<NDims>::type operator [](const boost::detail::multi_array::index_gen<NumDims,NDims> & indices) const333 operator[](const boost::detail::multi_array:: 334 index_gen<NumDims,NDims>& indices) 335 const { 336 return super_type::operator[](indices); 337 } 338 begin() const339 const_iterator begin() const { 340 return super_type::begin(); 341 } 342 end() const343 const_iterator end() const { 344 return super_type::end(); 345 } 346 rbegin() const347 const_reverse_iterator rbegin() const { 348 return super_type::rbegin(); 349 } 350 rend() const351 const_reverse_iterator rend() const { 352 return super_type::rend(); 353 } 354 355 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS 356 private: 357 template <typename,std::size_t> friend class value_accessor_n; 358 #else 359 public: // should be private 360 #endif 361 sub_array(T * base,const size_type * extents,const index * strides,const index * index_base)362 sub_array (T* base, 363 const size_type* extents, 364 const index* strides, 365 const index* index_base) : 366 super_type(base,extents,strides,index_base) { 367 } 368 369 }; 370 371 } // namespace multi_array 372 } // namespace detail 373 // 374 // traits classes to get sub_array types 375 // 376 template <typename Array, int N> 377 class subarray_gen { 378 typedef typename Array::element element; 379 public: 380 typedef boost::detail::multi_array::sub_array<element,N> type; 381 }; 382 383 template <typename Array, int N> 384 class const_subarray_gen { 385 typedef typename Array::element element; 386 public: 387 typedef boost::detail::multi_array::const_sub_array<element,N> type; 388 }; 389 } // namespace boost 390 391 #endif // SUBARRAY_RG071801_HPP 392