view.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  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_RG071301_HPP
  11. #define BOOST_MULTI_ARRAY_VIEW_RG071301_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. #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
  116. template <int NDims>
  117. #else
  118. template <int NumDims, int NDims> // else ICE
  119. #endif // BOOST_MSVC
  120. typename const_array_view<NDims>::type
  121. operator[](const boost::detail::multi_array::
  122. index_gen<NumDims,NDims>& indices)
  123. const {
  124. typedef typename const_array_view<NDims>::type return_type;
  125. return
  126. super_type::generate_array_view(boost::type<return_type>(),
  127. indices,
  128. shape(),
  129. strides(),
  130. index_bases(),
  131. origin());
  132. }
  133. const_iterator begin() const {
  134. return const_iterator(*index_bases(),origin(),
  135. shape(),strides(),index_bases());
  136. }
  137. const_iterator end() const {
  138. return const_iterator(*index_bases()+(index)*shape(),origin(),
  139. shape(),strides(),index_bases());
  140. }
  141. const_reverse_iterator rbegin() const {
  142. return const_reverse_iterator(end());
  143. }
  144. const_reverse_iterator rend() const {
  145. return const_reverse_iterator(begin());
  146. }
  147. template <typename OPtr>
  148. bool operator==(const
  149. const_multi_array_view<T,NumDims,OPtr>& rhs)
  150. const {
  151. if(std::equal(extent_list_.begin(),
  152. extent_list_.end(),
  153. rhs.extent_list_.begin()))
  154. return std::equal(begin(),end(),rhs.begin());
  155. else return false;
  156. }
  157. template <typename OPtr>
  158. bool operator<(const
  159. const_multi_array_view<T,NumDims,OPtr>& rhs)
  160. const {
  161. return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
  162. }
  163. template <typename OPtr>
  164. bool operator!=(const
  165. const_multi_array_view<T,NumDims,OPtr>& rhs)
  166. const {
  167. return !(*this == rhs);
  168. }
  169. template <typename OPtr>
  170. bool operator>(const
  171. const_multi_array_view<T,NumDims,OPtr>& rhs)
  172. const {
  173. return rhs < *this;
  174. }
  175. template <typename OPtr>
  176. bool operator<=(const
  177. const_multi_array_view<T,NumDims,OPtr>& rhs)
  178. const {
  179. return !(*this > rhs);
  180. }
  181. template <typename OPtr>
  182. bool operator>=(const
  183. const_multi_array_view<T,NumDims,OPtr>& rhs)
  184. const {
  185. return !(*this < rhs);
  186. }
  187. #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
  188. protected:
  189. template <typename,std::size_t> friend class multi_array_impl_base;
  190. template <typename,std::size_t,typename> friend class const_multi_array_view;
  191. #else
  192. public: // should be protected
  193. #endif
  194. // This constructor is used by multi_array_impl_base::generate_array_view
  195. // to create strides
  196. template <typename ExtentList, typename Index>
  197. explicit const_multi_array_view(TPtr base,
  198. const ExtentList& extents,
  199. const boost::array<Index,NumDims>& strides):
  200. base_(base), origin_offset_(0) {
  201. index_base_list_.assign(0);
  202. // Get the extents and strides
  203. boost::detail::multi_array::
  204. copy_n(extents.begin(),NumDims,extent_list_.begin());
  205. boost::detail::multi_array::
  206. copy_n(strides.begin(),NumDims,stride_list_.begin());
  207. // Calculate the array size
  208. num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
  209. size_type(1),std::multiplies<size_type>());
  210. }
  211. typedef boost::array<size_type,NumDims> size_list;
  212. typedef boost::array<index,NumDims> index_list;
  213. TPtr base_;
  214. index origin_offset_;
  215. size_type num_elements_;
  216. size_list extent_list_;
  217. index_list stride_list_;
  218. index_list index_base_list_;
  219. private:
  220. // const_multi_array_view cannot be assigned to (no deep copies!)
  221. const_multi_array_view& operator=(const const_multi_array_view& other);
  222. };
  223. template <typename T, std::size_t NumDims>
  224. class multi_array_view :
  225. public const_multi_array_view<T,NumDims,T*>
  226. {
  227. typedef const_multi_array_view<T,NumDims,T*> super_type;
  228. public:
  229. typedef typename super_type::value_type value_type;
  230. typedef typename super_type::reference reference;
  231. typedef typename super_type::iterator iterator;
  232. typedef typename super_type::reverse_iterator reverse_iterator;
  233. typedef typename super_type::const_reference const_reference;
  234. typedef typename super_type::const_iterator const_iterator;
  235. typedef typename super_type::const_reverse_iterator const_reverse_iterator;
  236. typedef typename super_type::element element;
  237. typedef typename super_type::size_type size_type;
  238. typedef typename super_type::difference_type difference_type;
  239. typedef typename super_type::index index;
  240. typedef typename super_type::extent_range extent_range;
  241. // template typedefs
  242. template <std::size_t NDims>
  243. struct const_array_view {
  244. typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
  245. };
  246. template <std::size_t NDims>
  247. struct array_view {
  248. typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
  249. };
  250. // Assignment from other ConstMultiArray types.
  251. template <typename ConstMultiArray>
  252. multi_array_view& operator=(const ConstMultiArray& other) {
  253. function_requires<
  254. boost::multi_array_concepts::
  255. ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
  256. // make sure the dimensions agree
  257. BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
  258. BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(),
  259. this->shape()));
  260. // iterator-based copy
  261. std::copy(other.begin(),other.end(),begin());
  262. return *this;
  263. }
  264. multi_array_view& operator=(const multi_array_view& other) {
  265. if (&other != this) {
  266. // make sure the dimensions agree
  267. BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
  268. BOOST_ASSERT(std::equal(other.shape(),
  269. other.shape()+this->num_dimensions(),
  270. this->shape()));
  271. // iterator-based copy
  272. std::copy(other.begin(),other.end(),begin());
  273. }
  274. return *this;
  275. }
  276. element* origin() { return this->base_+this->origin_offset_; }
  277. template <class IndexList>
  278. element& operator()(const IndexList& indices) {
  279. boost::function_requires<
  280. CollectionConcept<IndexList> >();
  281. return super_type::access_element(boost::type<element&>(),
  282. indices,origin(),
  283. this->shape(),this->strides(),
  284. this->index_bases());
  285. }
  286. reference operator[](index idx) {
  287. return super_type::access(boost::type<reference>(),
  288. idx,origin(),
  289. this->shape(),this->strides(),
  290. this->index_bases());
  291. }
  292. // see generate_array_view in base.hpp
  293. #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
  294. template <int NDims>
  295. #else
  296. template <int NumDims, int NDims> // else ICE
  297. #endif // BOOST_MSVC
  298. typename array_view<NDims>::type
  299. operator[](const boost::detail::multi_array::
  300. index_gen<NumDims,NDims>& indices) {
  301. typedef typename array_view<NDims>::type return_type;
  302. return
  303. super_type::generate_array_view(boost::type<return_type>(),
  304. indices,
  305. this->shape(),
  306. this->strides(),
  307. this->index_bases(),
  308. origin());
  309. }
  310. iterator begin() {
  311. return iterator(*this->index_bases(),origin(),
  312. this->shape(),this->strides(),
  313. this->index_bases());
  314. }
  315. iterator end() {
  316. return iterator(*this->index_bases()+(index)*this->shape(),origin(),
  317. this->shape(),this->strides(),
  318. this->index_bases());
  319. }
  320. reverse_iterator rbegin() {
  321. return reverse_iterator(end());
  322. }
  323. reverse_iterator rend() {
  324. return reverse_iterator(begin());
  325. }
  326. // Using declarations don't seem to work for g++
  327. // These are the proxies to work around this.
  328. const element* origin() const { return super_type::origin(); }
  329. template <class IndexList>
  330. const element& operator()(const IndexList& indices) const {
  331. boost::function_requires<
  332. CollectionConcept<IndexList> >();
  333. return super_type::operator()(indices);
  334. }
  335. const_reference operator[](index idx) const {
  336. return super_type::operator[](idx);
  337. }
  338. // see generate_array_view in base.hpp
  339. #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
  340. template <int NDims>
  341. #else
  342. template <int NumDims, int NDims> // else ICE
  343. #endif // BOOST_MSVC
  344. typename const_array_view<NDims>::type
  345. operator[](const boost::detail::multi_array::
  346. index_gen<NumDims,NDims>& indices)
  347. const {
  348. return super_type::operator[](indices);
  349. }
  350. const_iterator begin() const {
  351. return super_type::begin();
  352. }
  353. const_iterator end() const {
  354. return super_type::end();
  355. }
  356. const_reverse_iterator rbegin() const {
  357. return super_type::rbegin();
  358. }
  359. const_reverse_iterator rend() const {
  360. return super_type::rend();
  361. }
  362. #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
  363. private:
  364. template <typename,std::size_t> friend class multi_array_impl_base;
  365. #else
  366. public: // should be private
  367. #endif
  368. // constructor used by multi_array_impl_base::generate_array_view to
  369. // generate array views
  370. template <typename ExtentList, typename Index>
  371. explicit multi_array_view(T* base,
  372. const ExtentList& extents,
  373. const boost::array<Index,NumDims>& strides) :
  374. super_type(base,extents,strides) { }
  375. };
  376. } // namespace multi_array
  377. } // namespace detail
  378. //
  379. // traits classes to get array_view types
  380. //
  381. template <typename Array, int N>
  382. class array_view_gen {
  383. typedef typename Array::element element;
  384. public:
  385. typedef boost::detail::multi_array::multi_array_view<element,N> type;
  386. };
  387. template <typename Array, int N>
  388. class const_array_view_gen {
  389. typedef typename Array::element element;
  390. public:
  391. typedef boost::detail::multi_array::const_multi_array_view<element,N> type;
  392. };
  393. } // namespace boost
  394. #endif // BOOST_MULTI_ARRAY_VIEW_RG071301_HPP