view.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  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_VIEW_HPP
  11. #define BOOST_MULTI_ARRAY_VIEW_HPP
  12. //
  13. // view.hpp - code for creating "views" of array data.
  14. //
  15. #include "boost/multi_array/base.hpp"
  16. #include "boost/multi_array/concept_checks.hpp"
  17. #include "boost/multi_array/iterator.hpp"
  18. #include "boost/multi_array/storage_order.hpp"
  19. #include "boost/multi_array/subarray.hpp"
  20. #include "boost/multi_array/algorithm.hpp"
  21. #include "boost/type_traits/is_integral.hpp"
  22. #include "boost/utility/enable_if.hpp"
  23. #include "boost/array.hpp"
  24. #include "boost/limits.hpp"
  25. #include <algorithm>
  26. #include <cstddef>
  27. #include <functional>
  28. #include <numeric>
  29. namespace boost {
  30. namespace detail {
  31. namespace multi_array {
  32. // TPtr = const T* defaulted in base.hpp
  33. template <typename T, std::size_t NumDims, typename TPtr>
  34. class const_multi_array_view :
  35. public boost::detail::multi_array::multi_array_impl_base<T,NumDims>
  36. {
  37. typedef boost::detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
  38. public:
  39. typedef typename super_type::value_type value_type;
  40. typedef typename super_type::const_reference const_reference;
  41. typedef typename super_type::const_iterator const_iterator;
  42. typedef typename super_type::const_reverse_iterator const_reverse_iterator;
  43. typedef typename super_type::element element;
  44. typedef typename super_type::size_type size_type;
  45. typedef typename super_type::difference_type difference_type;
  46. typedef typename super_type::index index;
  47. typedef typename super_type::extent_range extent_range;
  48. // template typedefs
  49. template <std::size_t NDims>
  50. struct const_array_view {
  51. typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
  52. };
  53. template <std::size_t NDims>
  54. struct array_view {
  55. typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
  56. };
  57. template <typename OPtr>
  58. const_multi_array_view(const
  59. const_multi_array_view<T,NumDims,OPtr>& other) :
  60. base_(other.base_), origin_offset_(other.origin_offset_),
  61. num_elements_(other.num_elements_), extent_list_(other.extent_list_),
  62. stride_list_(other.stride_list_), index_base_list_(other.index_base_list_)
  63. { }
  64. template <class BaseList>
  65. #ifdef BOOST_NO_SFINAE
  66. void
  67. #else
  68. typename
  69. disable_if<typename boost::is_integral<BaseList>::type,void >::type
  70. #endif
  71. reindex(const BaseList& values) {
  72. boost::function_requires<
  73. CollectionConcept<BaseList> >();
  74. boost::detail::multi_array::
  75. copy_n(values.begin(),num_dimensions(),index_base_list_.begin());
  76. origin_offset_ =
  77. this->calculate_indexing_offset(stride_list_,index_base_list_);
  78. }
  79. void reindex(index value) {
  80. index_base_list_.assign(value);
  81. origin_offset_ =
  82. this->calculate_indexing_offset(stride_list_,index_base_list_);
  83. }
  84. size_type num_dimensions() const { return NumDims; }
  85. size_type size() const { return extent_list_.front(); }
  86. size_type max_size() const { return num_elements(); }
  87. bool empty() const { return size() == 0; }
  88. const size_type* shape() const {
  89. return extent_list_.data();
  90. }
  91. const index* strides() const {
  92. return stride_list_.data();
  93. }
  94. const T* origin() const { return base_+origin_offset_; }
  95. size_type num_elements() const { return num_elements_; }
  96. const index* index_bases() const {
  97. return index_base_list_.data();
  98. }
  99. template <typename IndexList>
  100. const element& operator()(IndexList indices) const {
  101. boost::function_requires<
  102. CollectionConcept<IndexList> >();
  103. return super_type::access_element(boost::type<const element&>(),
  104. indices,origin(),
  105. shape(),strides(),index_bases());
  106. }
  107. // Only allow const element access
  108. const_reference operator[](index idx) const {
  109. return super_type::access(boost::type<const_reference>(),
  110. idx,origin(),
  111. shape(),strides(),
  112. index_bases());
  113. }
  114. // see generate_array_view in base.hpp
  115. template <int NDims>
  116. typename const_array_view<NDims>::type
  117. operator[](const boost::detail::multi_array::
  118. index_gen<NumDims,NDims>& indices)
  119. const {
  120. typedef typename const_array_view<NDims>::type return_type;
  121. return
  122. super_type::generate_array_view(boost::type<return_type>(),
  123. indices,
  124. shape(),
  125. strides(),
  126. index_bases(),
  127. origin());
  128. }
  129. const_iterator begin() const {
  130. return const_iterator(*index_bases(),origin(),
  131. shape(),strides(),index_bases());
  132. }
  133. const_iterator end() const {
  134. return const_iterator(*index_bases()+(index)*shape(),origin(),
  135. shape(),strides(),index_bases());
  136. }
  137. const_reverse_iterator rbegin() const {
  138. return const_reverse_iterator(end());
  139. }
  140. const_reverse_iterator rend() const {
  141. return const_reverse_iterator(begin());
  142. }
  143. template <typename OPtr>
  144. bool operator==(const
  145. const_multi_array_view<T,NumDims,OPtr>& rhs)
  146. const {
  147. if(std::equal(extent_list_.begin(),
  148. extent_list_.end(),
  149. rhs.extent_list_.begin()))
  150. return std::equal(begin(),end(),rhs.begin());
  151. else return false;
  152. }
  153. template <typename OPtr>
  154. bool operator<(const
  155. const_multi_array_view<T,NumDims,OPtr>& rhs)
  156. const {
  157. return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
  158. }
  159. template <typename OPtr>
  160. bool operator!=(const
  161. const_multi_array_view<T,NumDims,OPtr>& rhs)
  162. const {
  163. return !(*this == rhs);
  164. }
  165. template <typename OPtr>
  166. bool operator>(const
  167. const_multi_array_view<T,NumDims,OPtr>& rhs)
  168. const {
  169. return rhs < *this;
  170. }
  171. template <typename OPtr>
  172. bool operator<=(const
  173. const_multi_array_view<T,NumDims,OPtr>& rhs)
  174. const {
  175. return !(*this > rhs);
  176. }
  177. template <typename OPtr>
  178. bool operator>=(const
  179. const_multi_array_view<T,NumDims,OPtr>& rhs)
  180. const {
  181. return !(*this < rhs);
  182. }
  183. #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
  184. protected:
  185. template <typename,std::size_t> friend class multi_array_impl_base;
  186. template <typename,std::size_t,typename> friend class const_multi_array_view;
  187. #else
  188. public: // should be protected
  189. #endif
  190. // This constructor is used by multi_array_impl_base::generate_array_view
  191. // to create strides
  192. template <typename ExtentList, typename Index>
  193. explicit const_multi_array_view(TPtr base,
  194. const ExtentList& extents,
  195. const boost::array<Index,NumDims>& strides):
  196. base_(base), origin_offset_(0) {
  197. index_base_list_.assign(0);
  198. // Get the extents and strides
  199. boost::detail::multi_array::
  200. copy_n(extents.begin(),NumDims,extent_list_.begin());
  201. boost::detail::multi_array::
  202. copy_n(strides.begin(),NumDims,stride_list_.begin());
  203. // Calculate the array size
  204. num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
  205. size_type(1),std::multiplies<size_type>());
  206. }
  207. typedef boost::array<size_type,NumDims> size_list;
  208. typedef boost::array<index,NumDims> index_list;
  209. TPtr base_;
  210. index origin_offset_;
  211. size_type num_elements_;
  212. size_list extent_list_;
  213. index_list stride_list_;
  214. index_list index_base_list_;
  215. private:
  216. // const_multi_array_view cannot be assigned to (no deep copies!)
  217. const_multi_array_view& operator=(const const_multi_array_view& other);
  218. };
  219. template <typename T, std::size_t NumDims>
  220. class multi_array_view :
  221. public const_multi_array_view<T,NumDims,T*>
  222. {
  223. typedef const_multi_array_view<T,NumDims,T*> super_type;
  224. public:
  225. typedef typename super_type::value_type value_type;
  226. typedef typename super_type::reference reference;
  227. typedef typename super_type::iterator iterator;
  228. typedef typename super_type::reverse_iterator reverse_iterator;
  229. typedef typename super_type::const_reference const_reference;
  230. typedef typename super_type::const_iterator const_iterator;
  231. typedef typename super_type::const_reverse_iterator const_reverse_iterator;
  232. typedef typename super_type::element element;
  233. typedef typename super_type::size_type size_type;
  234. typedef typename super_type::difference_type difference_type;
  235. typedef typename super_type::index index;
  236. typedef typename super_type::extent_range extent_range;
  237. // template typedefs
  238. template <std::size_t NDims>
  239. struct const_array_view {
  240. typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
  241. };
  242. template <std::size_t NDims>
  243. struct array_view {
  244. typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
  245. };
  246. // Assignment from other ConstMultiArray types.
  247. template <typename ConstMultiArray>
  248. multi_array_view& operator=(const ConstMultiArray& other) {
  249. function_requires<
  250. boost::multi_array_concepts::
  251. ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
  252. // make sure the dimensions agree
  253. BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
  254. BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(),
  255. this->shape()));
  256. // iterator-based copy
  257. std::copy(other.begin(),other.end(),begin());
  258. return *this;
  259. }
  260. multi_array_view& operator=(const multi_array_view& other) {
  261. if (&other != this) {
  262. // make sure the dimensions agree
  263. BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
  264. BOOST_ASSERT(std::equal(other.shape(),
  265. other.shape()+this->num_dimensions(),
  266. this->shape()));
  267. // iterator-based copy
  268. std::copy(other.begin(),other.end(),begin());
  269. }
  270. return *this;
  271. }
  272. element* origin() { return this->base_+this->origin_offset_; }
  273. template <class IndexList>
  274. element& operator()(const IndexList& indices) {
  275. boost::function_requires<
  276. CollectionConcept<IndexList> >();
  277. return super_type::access_element(boost::type<element&>(),
  278. indices,origin(),
  279. this->shape(),this->strides(),
  280. this->index_bases());
  281. }
  282. reference operator[](index idx) {
  283. return super_type::access(boost::type<reference>(),
  284. idx,origin(),
  285. this->shape(),this->strides(),
  286. this->index_bases());
  287. }
  288. // see generate_array_view in base.hpp
  289. template <int NDims>
  290. typename array_view<NDims>::type
  291. operator[](const boost::detail::multi_array::
  292. index_gen<NumDims,NDims>& indices) {
  293. typedef typename array_view<NDims>::type return_type;
  294. return
  295. super_type::generate_array_view(boost::type<return_type>(),
  296. indices,
  297. this->shape(),
  298. this->strides(),
  299. this->index_bases(),
  300. origin());
  301. }
  302. iterator begin() {
  303. return iterator(*this->index_bases(),origin(),
  304. this->shape(),this->strides(),
  305. this->index_bases());
  306. }
  307. iterator end() {
  308. return iterator(*this->index_bases()+(index)*this->shape(),origin(),
  309. this->shape(),this->strides(),
  310. this->index_bases());
  311. }
  312. reverse_iterator rbegin() {
  313. return reverse_iterator(end());
  314. }
  315. reverse_iterator rend() {
  316. return reverse_iterator(begin());
  317. }
  318. // Using declarations don't seem to work for g++
  319. // These are the proxies to work around this.
  320. const element* origin() const { return super_type::origin(); }
  321. template <class IndexList>
  322. const element& operator()(const IndexList& indices) const {
  323. boost::function_requires<
  324. CollectionConcept<IndexList> >();
  325. return super_type::operator()(indices);
  326. }
  327. const_reference operator[](index idx) const {
  328. return super_type::operator[](idx);
  329. }
  330. // see generate_array_view in base.hpp
  331. template <int NDims>
  332. typename const_array_view<NDims>::type
  333. operator[](const boost::detail::multi_array::
  334. index_gen<NumDims,NDims>& indices)
  335. const {
  336. return super_type::operator[](indices);
  337. }
  338. const_iterator begin() const {
  339. return super_type::begin();
  340. }
  341. const_iterator end() const {
  342. return super_type::end();
  343. }
  344. const_reverse_iterator rbegin() const {
  345. return super_type::rbegin();
  346. }
  347. const_reverse_iterator rend() const {
  348. return super_type::rend();
  349. }
  350. #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
  351. private:
  352. template <typename,std::size_t> friend class multi_array_impl_base;
  353. #else
  354. public: // should be private
  355. #endif
  356. // constructor used by multi_array_impl_base::generate_array_view to
  357. // generate array views
  358. template <typename ExtentList, typename Index>
  359. explicit multi_array_view(T* base,
  360. const ExtentList& extents,
  361. const boost::array<Index,NumDims>& strides) :
  362. super_type(base,extents,strides) { }
  363. };
  364. } // namespace multi_array
  365. } // namespace detail
  366. //
  367. // traits classes to get array_view types
  368. //
  369. template <typename Array, int N>
  370. class array_view_gen {
  371. typedef typename Array::element element;
  372. public:
  373. typedef boost::detail::multi_array::multi_array_view<element,N> type;
  374. };
  375. template <typename Array, int N>
  376. class const_array_view_gen {
  377. typedef typename Array::element element;
  378. public:
  379. typedef boost::detail::multi_array::const_multi_array_view<element,N> type;
  380. };
  381. } // namespace boost
  382. #endif