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 BOOST_MULTI_ARRAY_SUBARRAY_HPP 14 #define BOOST_MULTI_ARRAY_SUBARRAY_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 boost::function_requires< 83 CollectionConcept<IndexList> >(); 84 return super_type::access_element(boost::type<const element&>(), 85 indices,origin(), 86 shape(),strides(),index_bases()); 87 } 88 89 // see generate_array_view in base.hpp 90 template <int NDims> 91 typename const_array_view<NDims>::type operator [](const boost::detail::multi_array::index_gen<NumDims,NDims> & indices) const92 operator[](const boost::detail::multi_array:: 93 index_gen<NumDims,NDims>& indices) 94 const { 95 typedef typename const_array_view<NDims>::type return_type; 96 return 97 super_type::generate_array_view(boost::type<return_type>(), 98 indices, 99 shape(), 100 strides(), 101 index_bases(), 102 base_); 103 } 104 105 template <typename OPtr> operator <(const const_sub_array<T,NumDims,OPtr> & rhs) const106 bool operator<(const const_sub_array<T,NumDims,OPtr>& rhs) const { 107 return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end()); 108 } 109 110 template <typename OPtr> operator ==(const const_sub_array<T,NumDims,OPtr> & rhs) const111 bool operator==(const const_sub_array<T,NumDims,OPtr>& rhs) const { 112 if(std::equal(shape(),shape()+num_dimensions(),rhs.shape())) 113 return std::equal(begin(),end(),rhs.begin()); 114 else return false; 115 } 116 117 template <typename OPtr> operator !=(const const_sub_array<T,NumDims,OPtr> & rhs) const118 bool operator!=(const const_sub_array<T,NumDims,OPtr>& rhs) const { 119 return !(*this == rhs); 120 } 121 122 template <typename OPtr> operator >(const const_sub_array<T,NumDims,OPtr> & rhs) const123 bool operator>(const const_sub_array<T,NumDims,OPtr>& rhs) const { 124 return rhs < *this; 125 } 126 127 template <typename OPtr> operator <=(const const_sub_array<T,NumDims,OPtr> & rhs) const128 bool operator<=(const const_sub_array<T,NumDims,OPtr>& rhs) const { 129 return !(*this > rhs); 130 } 131 132 template <typename OPtr> operator >=(const const_sub_array<T,NumDims,OPtr> & rhs) const133 bool operator>=(const const_sub_array<T,NumDims,OPtr>& rhs) const { 134 return !(*this < rhs); 135 } 136 begin() const137 const_iterator begin() const { 138 return const_iterator(*index_bases(),origin(), 139 shape(),strides(),index_bases()); 140 } 141 end() const142 const_iterator end() const { 143 return const_iterator(*index_bases()+(index)*shape(),origin(), 144 shape(),strides(),index_bases()); 145 } 146 rbegin() const147 const_reverse_iterator rbegin() const { 148 return const_reverse_iterator(end()); 149 } 150 rend() const151 const_reverse_iterator rend() const { 152 return const_reverse_iterator(begin()); 153 } 154 origin() const155 TPtr origin() const { return base_; } size() const156 size_type size() const { return extents_[0]; } max_size() const157 size_type max_size() const { return num_elements(); } empty() const158 bool empty() const { return size() == 0; } num_dimensions() const159 size_type num_dimensions() const { return NumDims; } shape() const160 const size_type* shape() const { return extents_; } strides() const161 const index* strides() const { return strides_; } index_bases() const162 const index* index_bases() const { return index_base_; } 163 num_elements() const164 size_type num_elements() const { 165 return std::accumulate(shape(),shape() + num_dimensions(), 166 size_type(1), std::multiplies<size_type>()); 167 } 168 169 170 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS 171 protected: 172 template <typename,std::size_t> friend class value_accessor_n; 173 template <typename,std::size_t,typename> friend class const_sub_array; 174 #else 175 public: // Should be protected 176 #endif 177 const_sub_array(TPtr base,const size_type * extents,const index * strides,const index * index_base)178 const_sub_array (TPtr base, 179 const size_type* extents, 180 const index* strides, 181 const index* index_base) : 182 base_(base), extents_(extents), strides_(strides), 183 index_base_(index_base) { 184 } 185 186 TPtr base_; 187 const size_type* extents_; 188 const index* strides_; 189 const index* index_base_; 190 private: 191 // const_sub_array cannot be assigned to (no deep copies!) 192 const_sub_array& operator=(const const_sub_array&); 193 }; 194 195 196 // 197 // sub_array 198 // multi_array's proxy class to allow multiple overloads of 199 // operator[] in order to provide a clean multi-dimensional array 200 // interface. 201 template <typename T, std::size_t NumDims> 202 class sub_array : public const_sub_array<T,NumDims,T*> 203 { 204 typedef const_sub_array<T,NumDims,T*> super_type; 205 public: 206 typedef typename super_type::element element; 207 typedef typename super_type::reference reference; 208 typedef typename super_type::index index; 209 typedef typename super_type::size_type size_type; 210 typedef typename super_type::iterator iterator; 211 typedef typename super_type::reverse_iterator reverse_iterator; 212 typedef typename super_type::const_reference const_reference; 213 typedef typename super_type::const_iterator const_iterator; 214 typedef typename super_type::const_reverse_iterator const_reverse_iterator; 215 216 // template typedefs 217 template <std::size_t NDims> 218 struct const_array_view { 219 typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type; 220 }; 221 222 template <std::size_t NDims> 223 struct array_view { 224 typedef boost::detail::multi_array::multi_array_view<T,NDims> type; 225 }; 226 227 // Assignment from other ConstMultiArray types. 228 template <typename ConstMultiArray> operator =(const ConstMultiArray & other)229 sub_array& operator=(const ConstMultiArray& other) { 230 function_requires< boost::multi_array_concepts::ConstMultiArrayConcept< 231 ConstMultiArray, NumDims> >(); 232 233 // make sure the dimensions agree 234 BOOST_ASSERT(other.num_dimensions() == this->num_dimensions()); 235 BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(), 236 this->shape())); 237 // iterator-based copy 238 std::copy(other.begin(),other.end(),begin()); 239 return *this; 240 } 241 242 operator =(const sub_array & other)243 sub_array& operator=(const sub_array& other) { 244 if (&other != this) { 245 // make sure the dimensions agree 246 BOOST_ASSERT(other.num_dimensions() == this->num_dimensions()); 247 BOOST_ASSERT(std::equal(other.shape(), 248 other.shape()+this->num_dimensions(), 249 this->shape())); 250 // iterator-based copy 251 std::copy(other.begin(),other.end(),begin()); 252 } 253 return *this; 254 } 255 origin()256 T* origin() { return this->base_; } origin() const257 const T* origin() const { return this->base_; } 258 operator [](index idx)259 reference operator[](index idx) { 260 return super_type::access(boost::type<reference>(), 261 idx,this->base_,this->shape(),this->strides(), 262 this->index_bases()); 263 } 264 265 // see generate_array_view in base.hpp 266 template <int NDims> 267 typename array_view<NDims>::type operator [](const boost::detail::multi_array::index_gen<NumDims,NDims> & indices)268 operator[](const boost::detail::multi_array:: 269 index_gen<NumDims,NDims>& indices) { 270 typedef typename array_view<NDims>::type return_type; 271 return 272 super_type::generate_array_view(boost::type<return_type>(), 273 indices, 274 this->shape(), 275 this->strides(), 276 this->index_bases(), 277 origin()); 278 } 279 280 template <class IndexList> operator ()(const IndexList & indices)281 element& operator()(const IndexList& indices) { 282 boost::function_requires< 283 CollectionConcept<IndexList> >(); 284 return super_type::access_element(boost::type<element&>(), 285 indices,origin(), 286 this->shape(),this->strides(), 287 this->index_bases()); 288 } 289 begin()290 iterator begin() { 291 return iterator(*this->index_bases(),origin(), 292 this->shape(),this->strides(),this->index_bases()); 293 } 294 end()295 iterator end() { 296 return iterator(*this->index_bases()+(index)*this->shape(),origin(), 297 this->shape(),this->strides(),this->index_bases()); 298 } 299 300 // RG - rbegin() and rend() written naively to thwart MSVC ICE. rbegin()301 reverse_iterator rbegin() { 302 reverse_iterator ri(end()); 303 return ri; 304 } 305 rend()306 reverse_iterator rend() { 307 reverse_iterator ri(begin()); 308 return ri; 309 } 310 311 // 312 // proxies 313 // 314 315 template <class IndexList> operator ()(const IndexList & indices) const316 const element& operator()(const IndexList& indices) const { 317 boost::function_requires< 318 CollectionConcept<IndexList> >(); 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 template <int NDims> 328 typename const_array_view<NDims>::type operator [](const boost::detail::multi_array::index_gen<NumDims,NDims> & indices) const329 operator[](const boost::detail::multi_array:: 330 index_gen<NumDims,NDims>& indices) 331 const { 332 return super_type::operator[](indices); 333 } 334 begin() const335 const_iterator begin() const { 336 return super_type::begin(); 337 } 338 end() const339 const_iterator end() const { 340 return super_type::end(); 341 } 342 rbegin() const343 const_reverse_iterator rbegin() const { 344 return super_type::rbegin(); 345 } 346 rend() const347 const_reverse_iterator rend() const { 348 return super_type::rend(); 349 } 350 351 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS 352 private: 353 template <typename,std::size_t> friend class value_accessor_n; 354 #else 355 public: // should be private 356 #endif 357 sub_array(T * base,const size_type * extents,const index * strides,const index * index_base)358 sub_array (T* base, 359 const size_type* extents, 360 const index* strides, 361 const index* index_base) : 362 super_type(base,extents,strides,index_base) { 363 } 364 365 }; 366 367 } // namespace multi_array 368 } // namespace detail 369 // 370 // traits classes to get sub_array types 371 // 372 template <typename Array, int N> 373 class subarray_gen { 374 typedef typename Array::element element; 375 public: 376 typedef boost::detail::multi_array::sub_array<element,N> type; 377 }; 378 379 template <typename Array, int N> 380 class const_subarray_gen { 381 typedef typename Array::element element; 382 public: 383 typedef boost::detail::multi_array::const_sub_array<element,N> type; 384 }; 385 } // namespace boost 386 387 #endif 388