subarray.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. // Copyright 2002 The Trustees of Indiana University.
  2. // Use, modification and distribution is subject to the Boost Software
  3. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Boost.MultiArray Library
  6. // Authors: Ronald Garcia
  7. // Jeremy Siek
  8. // Andrew Lumsdaine
  9. // See http://www.boost.org/libs/multi_array for documentation.
  10. #ifndef BOOST_MULTI_ARRAY_SUBARRAY_HPP
  11. #define BOOST_MULTI_ARRAY_SUBARRAY_HPP
  12. //
  13. // subarray.hpp - used to implement standard operator[] on
  14. // multi_arrays
  15. //
  16. #include "boost/multi_array/base.hpp"
  17. #include "boost/multi_array/concept_checks.hpp"
  18. #include "boost/limits.hpp"
  19. #include "boost/type.hpp"
  20. #include <algorithm>
  21. #include <cstddef>
  22. #include <functional>
  23. namespace boost {
  24. namespace detail {
  25. namespace multi_array {
  26. //
  27. // const_sub_array
  28. // multi_array's proxy class to allow multiple overloads of
  29. // operator[] in order to provide a clean multi-dimensional array
  30. // interface.
  31. template <typename T, std::size_t NumDims, typename TPtr>
  32. class const_sub_array :
  33. public boost::detail::multi_array::multi_array_impl_base<T,NumDims>
  34. {
  35. typedef boost::detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
  36. public:
  37. typedef typename super_type::value_type value_type;
  38. typedef typename super_type::const_reference const_reference;
  39. typedef typename super_type::const_iterator const_iterator;
  40. typedef typename super_type::const_reverse_iterator const_reverse_iterator;
  41. typedef typename super_type::element element;
  42. typedef typename super_type::size_type size_type;
  43. typedef typename super_type::difference_type difference_type;
  44. typedef typename super_type::index index;
  45. typedef typename super_type::extent_range extent_range;
  46. // template typedefs
  47. template <std::size_t NDims>
  48. struct const_array_view {
  49. typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
  50. };
  51. template <std::size_t NDims>
  52. struct array_view {
  53. typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
  54. };
  55. // Allow default copy constructor as well.
  56. template <typename OPtr>
  57. const_sub_array (const const_sub_array<T,NumDims,OPtr>& rhs) :
  58. base_(rhs.base_), extents_(rhs.extents_), strides_(rhs.strides_),
  59. index_base_(rhs.index_base_) {
  60. }
  61. // const_sub_array always returns const types, regardless of its own
  62. // constness.
  63. const_reference operator[](index idx) const {
  64. return super_type::access(boost::type<const_reference>(),
  65. idx,base_,shape(),strides(),index_bases());
  66. }
  67. template <typename IndexList>
  68. const element& operator()(const IndexList& indices) const {
  69. boost::function_requires<
  70. CollectionConcept<IndexList> >();
  71. return super_type::access_element(boost::type<const element&>(),
  72. indices,origin(),
  73. shape(),strides(),index_bases());
  74. }
  75. // see generate_array_view in base.hpp
  76. template <int NDims>
  77. typename const_array_view<NDims>::type
  78. operator[](const boost::detail::multi_array::
  79. index_gen<NumDims,NDims>& indices)
  80. const {
  81. typedef typename const_array_view<NDims>::type return_type;
  82. return
  83. super_type::generate_array_view(boost::type<return_type>(),
  84. indices,
  85. shape(),
  86. strides(),
  87. index_bases(),
  88. base_);
  89. }
  90. template <typename OPtr>
  91. bool operator<(const const_sub_array<T,NumDims,OPtr>& rhs) const {
  92. return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
  93. }
  94. template <typename OPtr>
  95. bool operator==(const const_sub_array<T,NumDims,OPtr>& rhs) const {
  96. if(std::equal(shape(),shape()+num_dimensions(),rhs.shape()))
  97. return std::equal(begin(),end(),rhs.begin());
  98. else return false;
  99. }
  100. template <typename OPtr>
  101. bool operator!=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
  102. return !(*this == rhs);
  103. }
  104. template <typename OPtr>
  105. bool operator>(const const_sub_array<T,NumDims,OPtr>& rhs) const {
  106. return rhs < *this;
  107. }
  108. template <typename OPtr>
  109. bool operator<=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
  110. return !(*this > rhs);
  111. }
  112. template <typename OPtr>
  113. bool operator>=(const const_sub_array<T,NumDims,OPtr>& rhs) const {
  114. return !(*this < rhs);
  115. }
  116. const_iterator begin() const {
  117. return const_iterator(*index_bases(),origin(),
  118. shape(),strides(),index_bases());
  119. }
  120. const_iterator end() const {
  121. return const_iterator(*index_bases()+(index)*shape(),origin(),
  122. shape(),strides(),index_bases());
  123. }
  124. const_reverse_iterator rbegin() const {
  125. return const_reverse_iterator(end());
  126. }
  127. const_reverse_iterator rend() const {
  128. return const_reverse_iterator(begin());
  129. }
  130. TPtr origin() const { return base_; }
  131. size_type size() const { return extents_[0]; }
  132. size_type max_size() const { return num_elements(); }
  133. bool empty() const { return size() == 0; }
  134. size_type num_dimensions() const { return NumDims; }
  135. const size_type* shape() const { return extents_; }
  136. const index* strides() const { return strides_; }
  137. const index* index_bases() const { return index_base_; }
  138. size_type num_elements() const {
  139. return std::accumulate(shape(),shape() + num_dimensions(),
  140. size_type(1), std::multiplies<size_type>());
  141. }
  142. #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
  143. protected:
  144. template <typename,std::size_t> friend class value_accessor_n;
  145. template <typename,std::size_t,typename> friend class const_sub_array;
  146. #else
  147. public: // Should be protected
  148. #endif
  149. const_sub_array (TPtr base,
  150. const size_type* extents,
  151. const index* strides,
  152. const index* index_base) :
  153. base_(base), extents_(extents), strides_(strides),
  154. index_base_(index_base) {
  155. }
  156. TPtr base_;
  157. const size_type* extents_;
  158. const index* strides_;
  159. const index* index_base_;
  160. private:
  161. // const_sub_array cannot be assigned to (no deep copies!)
  162. const_sub_array& operator=(const const_sub_array&);
  163. };
  164. //
  165. // sub_array
  166. // multi_array's proxy class to allow multiple overloads of
  167. // operator[] in order to provide a clean multi-dimensional array
  168. // interface.
  169. template <typename T, std::size_t NumDims>
  170. class sub_array : public const_sub_array<T,NumDims,T*>
  171. {
  172. typedef const_sub_array<T,NumDims,T*> super_type;
  173. public:
  174. typedef typename super_type::element element;
  175. typedef typename super_type::reference reference;
  176. typedef typename super_type::index index;
  177. typedef typename super_type::size_type size_type;
  178. typedef typename super_type::iterator iterator;
  179. typedef typename super_type::reverse_iterator reverse_iterator;
  180. typedef typename super_type::const_reference const_reference;
  181. typedef typename super_type::const_iterator const_iterator;
  182. typedef typename super_type::const_reverse_iterator const_reverse_iterator;
  183. // template typedefs
  184. template <std::size_t NDims>
  185. struct const_array_view {
  186. typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
  187. };
  188. template <std::size_t NDims>
  189. struct array_view {
  190. typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
  191. };
  192. // Assignment from other ConstMultiArray types.
  193. template <typename ConstMultiArray>
  194. sub_array& operator=(const ConstMultiArray& other) {
  195. function_requires< boost::multi_array_concepts::ConstMultiArrayConcept<
  196. ConstMultiArray, NumDims> >();
  197. // make sure the dimensions agree
  198. BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
  199. BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(),
  200. this->shape()));
  201. // iterator-based copy
  202. std::copy(other.begin(),other.end(),begin());
  203. return *this;
  204. }
  205. sub_array& operator=(const sub_array& other) {
  206. if (&other != this) {
  207. // make sure the dimensions agree
  208. BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
  209. BOOST_ASSERT(std::equal(other.shape(),
  210. other.shape()+this->num_dimensions(),
  211. this->shape()));
  212. // iterator-based copy
  213. std::copy(other.begin(),other.end(),begin());
  214. }
  215. return *this;
  216. }
  217. T* origin() { return this->base_; }
  218. const T* origin() const { return this->base_; }
  219. reference operator[](index idx) {
  220. return super_type::access(boost::type<reference>(),
  221. idx,this->base_,this->shape(),this->strides(),
  222. this->index_bases());
  223. }
  224. // see generate_array_view in base.hpp
  225. template <int NDims>
  226. typename array_view<NDims>::type
  227. operator[](const boost::detail::multi_array::
  228. index_gen<NumDims,NDims>& indices) {
  229. typedef typename array_view<NDims>::type return_type;
  230. return
  231. super_type::generate_array_view(boost::type<return_type>(),
  232. indices,
  233. this->shape(),
  234. this->strides(),
  235. this->index_bases(),
  236. origin());
  237. }
  238. template <class IndexList>
  239. element& operator()(const IndexList& indices) {
  240. boost::function_requires<
  241. CollectionConcept<IndexList> >();
  242. return super_type::access_element(boost::type<element&>(),
  243. indices,origin(),
  244. this->shape(),this->strides(),
  245. this->index_bases());
  246. }
  247. iterator begin() {
  248. return iterator(*this->index_bases(),origin(),
  249. this->shape(),this->strides(),this->index_bases());
  250. }
  251. iterator end() {
  252. return iterator(*this->index_bases()+(index)*this->shape(),origin(),
  253. this->shape(),this->strides(),this->index_bases());
  254. }
  255. // RG - rbegin() and rend() written naively to thwart MSVC ICE.
  256. reverse_iterator rbegin() {
  257. reverse_iterator ri(end());
  258. return ri;
  259. }
  260. reverse_iterator rend() {
  261. reverse_iterator ri(begin());
  262. return ri;
  263. }
  264. //
  265. // proxies
  266. //
  267. template <class IndexList>
  268. const element& operator()(const IndexList& indices) const {
  269. boost::function_requires<
  270. CollectionConcept<IndexList> >();
  271. return super_type::operator()(indices);
  272. }
  273. const_reference operator[](index idx) const {
  274. return super_type::operator[](idx);
  275. }
  276. // see generate_array_view in base.hpp
  277. template <int NDims>
  278. typename const_array_view<NDims>::type
  279. operator[](const boost::detail::multi_array::
  280. index_gen<NumDims,NDims>& indices)
  281. const {
  282. return super_type::operator[](indices);
  283. }
  284. const_iterator begin() const {
  285. return super_type::begin();
  286. }
  287. const_iterator end() const {
  288. return super_type::end();
  289. }
  290. const_reverse_iterator rbegin() const {
  291. return super_type::rbegin();
  292. }
  293. const_reverse_iterator rend() const {
  294. return super_type::rend();
  295. }
  296. #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
  297. private:
  298. template <typename,std::size_t> friend class value_accessor_n;
  299. #else
  300. public: // should be private
  301. #endif
  302. sub_array (T* base,
  303. const size_type* extents,
  304. const index* strides,
  305. const index* index_base) :
  306. super_type(base,extents,strides,index_base) {
  307. }
  308. };
  309. } // namespace multi_array
  310. } // namespace detail
  311. //
  312. // traits classes to get sub_array types
  313. //
  314. template <typename Array, int N>
  315. class subarray_gen {
  316. typedef typename Array::element element;
  317. public:
  318. typedef boost::detail::multi_array::sub_array<element,N> type;
  319. };
  320. template <typename Array, int N>
  321. class const_subarray_gen {
  322. typedef typename Array::element element;
  323. public:
  324. typedef boost::detail::multi_array::const_sub_array<element,N> type;
  325. };
  326. } // namespace boost
  327. #endif