/Src/Dependencies/Boost/boost/multi_array/multi_array_ref.hpp

http://hadesmem.googlecode.com/ · C++ Header · 633 lines · 482 code · 111 blank · 40 comment · 18 complexity · c9a97617573dceb1a55a343a110e30ed MD5 · raw file

  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_REF_RG071801_HPP
  11. #define BOOST_MULTI_ARRAY_REF_RG071801_HPP
  12. //
  13. // multi_array_ref.hpp - code for creating "views" of array data.
  14. //
  15. #include "boost/multi_array/base.hpp"
  16. #include "boost/multi_array/collection_concept.hpp"
  17. #include "boost/multi_array/concept_checks.hpp"
  18. #include "boost/multi_array/iterator.hpp"
  19. #include "boost/multi_array/storage_order.hpp"
  20. #include "boost/multi_array/subarray.hpp"
  21. #include "boost/multi_array/view.hpp"
  22. #include "boost/multi_array/algorithm.hpp"
  23. #include "boost/type_traits/is_integral.hpp"
  24. #include "boost/array.hpp"
  25. #include "boost/concept_check.hpp"
  26. #include "boost/functional.hpp"
  27. #include "boost/limits.hpp"
  28. #include <algorithm>
  29. #include <cstddef>
  30. #include <functional>
  31. #include <numeric>
  32. namespace boost {
  33. template <typename T, std::size_t NumDims,
  34. typename TPtr = const T*
  35. >
  36. class const_multi_array_ref :
  37. public detail::multi_array::multi_array_impl_base<T,NumDims>
  38. {
  39. typedef detail::multi_array::multi_array_impl_base<T,NumDims> super_type;
  40. public:
  41. typedef typename super_type::value_type value_type;
  42. typedef typename super_type::const_reference const_reference;
  43. typedef typename super_type::const_iterator const_iterator;
  44. typedef typename super_type::const_reverse_iterator const_reverse_iterator;
  45. typedef typename super_type::element element;
  46. typedef typename super_type::size_type size_type;
  47. typedef typename super_type::difference_type difference_type;
  48. typedef typename super_type::index index;
  49. typedef typename super_type::extent_range extent_range;
  50. typedef general_storage_order<NumDims> storage_order_type;
  51. // template typedefs
  52. template <std::size_t NDims>
  53. struct const_array_view {
  54. typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
  55. };
  56. template <std::size_t NDims>
  57. struct array_view {
  58. typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
  59. };
  60. #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
  61. // make const_multi_array_ref a friend of itself
  62. template <typename,std::size_t,typename>
  63. friend class const_multi_array_ref;
  64. #endif
  65. // This ensures that const_multi_array_ref types with different TPtr
  66. // types can convert to each other
  67. template <typename OPtr>
  68. const_multi_array_ref(const const_multi_array_ref<T,NumDims,OPtr>& other)
  69. : base_(other.base_), storage_(other.storage_),
  70. extent_list_(other.extent_list_),
  71. stride_list_(other.stride_list_),
  72. index_base_list_(other.index_base_list_),
  73. origin_offset_(other.origin_offset_),
  74. directional_offset_(other.directional_offset_),
  75. num_elements_(other.num_elements_) { }
  76. template <typename ExtentList>
  77. explicit const_multi_array_ref(TPtr base, const ExtentList& extents) :
  78. base_(base), storage_(c_storage_order()) {
  79. boost::function_requires<
  80. CollectionConcept<ExtentList> >();
  81. index_base_list_.assign(0);
  82. init_multi_array_ref(extents.begin());
  83. }
  84. template <typename ExtentList>
  85. explicit const_multi_array_ref(TPtr base, const ExtentList& extents,
  86. const general_storage_order<NumDims>& so) :
  87. base_(base), storage_(so) {
  88. boost::function_requires<
  89. CollectionConcept<ExtentList> >();
  90. index_base_list_.assign(0);
  91. init_multi_array_ref(extents.begin());
  92. }
  93. explicit const_multi_array_ref(TPtr base,
  94. const detail::multi_array::
  95. extent_gen<NumDims>& ranges) :
  96. base_(base), storage_(c_storage_order()) {
  97. init_from_extent_gen(ranges);
  98. }
  99. explicit const_multi_array_ref(TPtr base,
  100. const detail::multi_array::
  101. extent_gen<NumDims>& ranges,
  102. const general_storage_order<NumDims>& so) :
  103. base_(base), storage_(so) {
  104. init_from_extent_gen(ranges);
  105. }
  106. template <class InputIterator>
  107. void assign(InputIterator begin, InputIterator end) {
  108. boost::function_requires<InputIteratorConcept<InputIterator> >();
  109. InputIterator in_iter = begin;
  110. T* out_iter = base_;
  111. std::size_t copy_count=0;
  112. while (in_iter != end && copy_count < num_elements_) {
  113. *out_iter++ = *in_iter++;
  114. copy_count++;
  115. }
  116. }
  117. template <class BaseList>
  118. #ifdef BOOST_NO_SFINAE
  119. void
  120. #else
  121. typename
  122. disable_if<typename boost::is_integral<BaseList>::type,void >::type
  123. #endif // BOOST_NO_SFINAE
  124. reindex(const BaseList& values) {
  125. boost::function_requires<
  126. CollectionConcept<BaseList> >();
  127. boost::detail::multi_array::
  128. copy_n(values.begin(),num_dimensions(),index_base_list_.begin());
  129. origin_offset_ =
  130. this->calculate_origin_offset(stride_list_,extent_list_,
  131. storage_,index_base_list_);
  132. }
  133. void reindex(index value) {
  134. index_base_list_.assign(value);
  135. origin_offset_ =
  136. this->calculate_origin_offset(stride_list_,extent_list_,
  137. storage_,index_base_list_);
  138. }
  139. template <typename SizeList>
  140. void reshape(const SizeList& extents) {
  141. boost::function_requires<
  142. CollectionConcept<SizeList> >();
  143. BOOST_ASSERT(num_elements_ ==
  144. std::accumulate(extents.begin(),extents.end(),
  145. size_type(1),std::multiplies<size_type>()));
  146. std::copy(extents.begin(),extents.end(),extent_list_.begin());
  147. this->compute_strides(stride_list_,extent_list_,storage_);
  148. origin_offset_ =
  149. this->calculate_origin_offset(stride_list_,extent_list_,
  150. storage_,index_base_list_);
  151. }
  152. size_type num_dimensions() const { return NumDims; }
  153. size_type size() const { return extent_list_.front(); }
  154. // given reshaping functionality, this is the max possible size.
  155. size_type max_size() const { return num_elements(); }
  156. bool empty() const { return size() == 0; }
  157. const size_type* shape() const {
  158. return extent_list_.data();
  159. }
  160. const index* strides() const {
  161. return stride_list_.data();
  162. }
  163. const element* origin() const { return base_+origin_offset_; }
  164. const element* data() const { return base_; }
  165. size_type num_elements() const { return num_elements_; }
  166. const index* index_bases() const {
  167. return index_base_list_.data();
  168. }
  169. const storage_order_type& storage_order() const {
  170. return storage_;
  171. }
  172. template <typename IndexList>
  173. const element& operator()(IndexList indices) const {
  174. boost::function_requires<
  175. CollectionConcept<IndexList> >();
  176. return super_type::access_element(boost::type<const element&>(),
  177. indices,origin(),
  178. shape(),strides(),index_bases());
  179. }
  180. // Only allow const element access
  181. const_reference operator[](index idx) const {
  182. return super_type::access(boost::type<const_reference>(),
  183. idx,origin(),
  184. shape(),strides(),index_bases());
  185. }
  186. // see generate_array_view in base.hpp
  187. #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
  188. template <int NDims>
  189. #else
  190. template <int NumDims, int NDims> // else ICE
  191. #endif // BOOST_MSVC
  192. typename const_array_view<NDims>::type
  193. operator[](const detail::multi_array::
  194. index_gen<NumDims,NDims>& indices)
  195. const {
  196. typedef typename const_array_view<NDims>::type return_type;
  197. return
  198. super_type::generate_array_view(boost::type<return_type>(),
  199. indices,
  200. shape(),
  201. strides(),
  202. index_bases(),
  203. origin());
  204. }
  205. const_iterator begin() const {
  206. return const_iterator(*index_bases(),origin(),
  207. shape(),strides(),index_bases());
  208. }
  209. const_iterator end() const {
  210. return const_iterator(*index_bases()+(index)*shape(),origin(),
  211. shape(),strides(),index_bases());
  212. }
  213. const_reverse_iterator rbegin() const {
  214. return const_reverse_iterator(end());
  215. }
  216. const_reverse_iterator rend() const {
  217. return const_reverse_iterator(begin());
  218. }
  219. template <typename OPtr>
  220. bool operator==(const
  221. const_multi_array_ref<T,NumDims,OPtr>& rhs)
  222. const {
  223. if(std::equal(extent_list_.begin(),
  224. extent_list_.end(),
  225. rhs.extent_list_.begin()))
  226. return std::equal(begin(),end(),rhs.begin());
  227. else return false;
  228. }
  229. template <typename OPtr>
  230. bool operator<(const
  231. const_multi_array_ref<T,NumDims,OPtr>& rhs)
  232. const {
  233. return std::lexicographical_compare(begin(),end(),rhs.begin(),rhs.end());
  234. }
  235. template <typename OPtr>
  236. bool operator!=(const
  237. const_multi_array_ref<T,NumDims,OPtr>& rhs)
  238. const {
  239. return !(*this == rhs);
  240. }
  241. template <typename OPtr>
  242. bool operator>(const
  243. const_multi_array_ref<T,NumDims,OPtr>& rhs)
  244. const {
  245. return rhs < *this;
  246. }
  247. template <typename OPtr>
  248. bool operator<=(const
  249. const_multi_array_ref<T,NumDims,OPtr>& rhs)
  250. const {
  251. return !(*this > rhs);
  252. }
  253. template <typename OPtr>
  254. bool operator>=(const
  255. const_multi_array_ref<T,NumDims,OPtr>& rhs)
  256. const {
  257. return !(*this < rhs);
  258. }
  259. #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
  260. protected:
  261. #else
  262. public:
  263. #endif
  264. typedef boost::array<size_type,NumDims> size_list;
  265. typedef boost::array<index,NumDims> index_list;
  266. // This is used by multi_array, which is a subclass of this
  267. void set_base_ptr(TPtr new_base) { base_ = new_base; }
  268. // This constructor supports multi_array's default constructor
  269. // and constructors from multi_array_ref, subarray, and array_view
  270. explicit
  271. const_multi_array_ref(TPtr base,
  272. const storage_order_type& so,
  273. const index * index_bases,
  274. const size_type* extents) :
  275. base_(base), storage_(so), origin_offset_(0), directional_offset_(0)
  276. {
  277. // If index_bases or extents is null, then initialize the corresponding
  278. // private data to zeroed lists.
  279. if(index_bases) {
  280. boost::detail::multi_array::
  281. copy_n(index_bases,NumDims,index_base_list_.begin());
  282. } else {
  283. std::fill_n(index_base_list_.begin(),NumDims,0);
  284. }
  285. if(extents) {
  286. init_multi_array_ref(extents);
  287. } else {
  288. boost::array<index,NumDims> extent_list;
  289. extent_list.assign(0);
  290. init_multi_array_ref(extent_list.begin());
  291. }
  292. }
  293. TPtr base_;
  294. storage_order_type storage_;
  295. size_list extent_list_;
  296. index_list stride_list_;
  297. index_list index_base_list_;
  298. index origin_offset_;
  299. index directional_offset_;
  300. size_type num_elements_;
  301. private:
  302. // const_multi_array_ref cannot be assigned to (no deep copies!)
  303. const_multi_array_ref& operator=(const const_multi_array_ref& other);
  304. void init_from_extent_gen(const
  305. detail::multi_array::
  306. extent_gen<NumDims>& ranges) {
  307. typedef boost::array<index,NumDims> extent_list;
  308. // get the index_base values
  309. std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
  310. index_base_list_.begin(),
  311. boost::mem_fun_ref(&extent_range::start));
  312. // calculate the extents
  313. extent_list extents;
  314. std::transform(ranges.ranges_.begin(),ranges.ranges_.end(),
  315. extents.begin(),
  316. boost::mem_fun_ref(&extent_range::size));
  317. init_multi_array_ref(extents.begin());
  318. }
  319. #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
  320. protected:
  321. #else
  322. public:
  323. #endif
  324. // RG - move me!
  325. template <class InputIterator>
  326. void init_multi_array_ref(InputIterator extents_iter) {
  327. boost::function_requires<InputIteratorConcept<InputIterator> >();
  328. boost::detail::multi_array::
  329. copy_n(extents_iter,num_dimensions(),extent_list_.begin());
  330. // Calculate the array size
  331. num_elements_ = std::accumulate(extent_list_.begin(),extent_list_.end(),
  332. size_type(1),std::multiplies<size_type>());
  333. this->compute_strides(stride_list_,extent_list_,storage_);
  334. origin_offset_ =
  335. this->calculate_origin_offset(stride_list_,extent_list_,
  336. storage_,index_base_list_);
  337. directional_offset_ =
  338. this->calculate_descending_dimension_offset(stride_list_,extent_list_,
  339. storage_);
  340. }
  341. };
  342. template <typename T, std::size_t NumDims>
  343. class multi_array_ref :
  344. public const_multi_array_ref<T,NumDims,T*>
  345. {
  346. typedef const_multi_array_ref<T,NumDims,T*> super_type;
  347. public:
  348. typedef typename super_type::value_type value_type;
  349. typedef typename super_type::reference reference;
  350. typedef typename super_type::iterator iterator;
  351. typedef typename super_type::reverse_iterator reverse_iterator;
  352. typedef typename super_type::const_reference const_reference;
  353. typedef typename super_type::const_iterator const_iterator;
  354. typedef typename super_type::const_reverse_iterator const_reverse_iterator;
  355. typedef typename super_type::element element;
  356. typedef typename super_type::size_type size_type;
  357. typedef typename super_type::difference_type difference_type;
  358. typedef typename super_type::index index;
  359. typedef typename super_type::extent_range extent_range;
  360. typedef typename super_type::storage_order_type storage_order_type;
  361. typedef typename super_type::index_list index_list;
  362. typedef typename super_type::size_list size_list;
  363. template <std::size_t NDims>
  364. struct const_array_view {
  365. typedef boost::detail::multi_array::const_multi_array_view<T,NDims> type;
  366. };
  367. template <std::size_t NDims>
  368. struct array_view {
  369. typedef boost::detail::multi_array::multi_array_view<T,NDims> type;
  370. };
  371. template <class ExtentList>
  372. explicit multi_array_ref(T* base, const ExtentList& extents) :
  373. super_type(base,extents) {
  374. boost::function_requires<
  375. CollectionConcept<ExtentList> >();
  376. }
  377. template <class ExtentList>
  378. explicit multi_array_ref(T* base, const ExtentList& extents,
  379. const general_storage_order<NumDims>& so) :
  380. super_type(base,extents,so) {
  381. boost::function_requires<
  382. CollectionConcept<ExtentList> >();
  383. }
  384. explicit multi_array_ref(T* base,
  385. const detail::multi_array::
  386. extent_gen<NumDims>& ranges) :
  387. super_type(base,ranges) { }
  388. explicit multi_array_ref(T* base,
  389. const detail::multi_array::
  390. extent_gen<NumDims>&
  391. ranges,
  392. const general_storage_order<NumDims>& so) :
  393. super_type(base,ranges,so) { }
  394. // Assignment from other ConstMultiArray types.
  395. template <typename ConstMultiArray>
  396. multi_array_ref& operator=(const ConstMultiArray& other) {
  397. function_requires<
  398. multi_array_concepts::
  399. ConstMultiArrayConcept<ConstMultiArray,NumDims> >();
  400. // make sure the dimensions agree
  401. BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
  402. BOOST_ASSERT(std::equal(other.shape(),other.shape()+this->num_dimensions(),
  403. this->shape()));
  404. // iterator-based copy
  405. std::copy(other.begin(),other.end(),this->begin());
  406. return *this;
  407. }
  408. multi_array_ref& operator=(const multi_array_ref& other) {
  409. if (&other != this) {
  410. // make sure the dimensions agree
  411. BOOST_ASSERT(other.num_dimensions() == this->num_dimensions());
  412. BOOST_ASSERT(std::equal(other.shape(),
  413. other.shape()+this->num_dimensions(),
  414. this->shape()));
  415. // iterator-based copy
  416. std::copy(other.begin(),other.end(),this->begin());
  417. }
  418. return *this;
  419. }
  420. element* origin() { return super_type::base_+super_type::origin_offset_; }
  421. element* data() { return super_type::base_; }
  422. template <class IndexList>
  423. element& operator()(const IndexList& indices) {
  424. boost::function_requires<
  425. CollectionConcept<IndexList> >();
  426. return super_type::access_element(boost::type<element&>(),
  427. indices,origin(),
  428. this->shape(),this->strides(),
  429. this->index_bases());
  430. }
  431. reference operator[](index idx) {
  432. return super_type::access(boost::type<reference>(),
  433. idx,origin(),
  434. this->shape(),this->strides(),
  435. this->index_bases());
  436. }
  437. // See note attached to generate_array_view in base.hpp
  438. #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
  439. template <int NDims>
  440. #else
  441. template <int NumDims, int NDims> // else ICE
  442. #endif // BOOST_MSVC
  443. typename array_view<NDims>::type
  444. operator[](const detail::multi_array::
  445. index_gen<NumDims,NDims>& indices) {
  446. typedef typename array_view<NDims>::type return_type;
  447. return
  448. super_type::generate_array_view(boost::type<return_type>(),
  449. indices,
  450. this->shape(),
  451. this->strides(),
  452. this->index_bases(),
  453. origin());
  454. }
  455. iterator begin() {
  456. return iterator(*this->index_bases(),origin(),this->shape(),
  457. this->strides(),this->index_bases());
  458. }
  459. iterator end() {
  460. return iterator(*this->index_bases()+(index)*this->shape(),origin(),
  461. this->shape(),this->strides(),
  462. this->index_bases());
  463. }
  464. // rbegin() and rend() written naively to thwart MSVC ICE.
  465. reverse_iterator rbegin() {
  466. reverse_iterator ri(end());
  467. return ri;
  468. }
  469. reverse_iterator rend() {
  470. reverse_iterator ri(begin());
  471. return ri;
  472. }
  473. // Using declarations don't seem to work for g++
  474. // These are the proxies to work around this.
  475. const element* origin() const { return super_type::origin(); }
  476. const element* data() const { return super_type::data(); }
  477. template <class IndexList>
  478. const element& operator()(const IndexList& indices) const {
  479. boost::function_requires<
  480. CollectionConcept<IndexList> >();
  481. return super_type::operator()(indices);
  482. }
  483. const_reference operator[](index idx) const {
  484. return super_type::access(boost::type<const_reference>(),
  485. idx,origin(),
  486. this->shape(),this->strides(),
  487. this->index_bases());
  488. }
  489. // See note attached to generate_array_view in base.hpp
  490. #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
  491. template <int NDims>
  492. #else
  493. template <int NumDims, int NDims> // else ICE
  494. #endif // BOOST_MSVC
  495. typename const_array_view<NDims>::type
  496. operator[](const detail::multi_array::
  497. index_gen<NumDims,NDims>& indices)
  498. const {
  499. return super_type::operator[](indices);
  500. }
  501. const_iterator begin() const {
  502. return super_type::begin();
  503. }
  504. const_iterator end() const {
  505. return super_type::end();
  506. }
  507. const_reverse_iterator rbegin() const {
  508. return super_type::rbegin();
  509. }
  510. const_reverse_iterator rend() const {
  511. return super_type::rend();
  512. }
  513. protected:
  514. // This is only supplied to support multi_array's default constructor
  515. explicit multi_array_ref(T* base,
  516. const storage_order_type& so,
  517. const index* index_bases,
  518. const size_type* extents) :
  519. super_type(base,so,index_bases,extents) { }
  520. };
  521. } // namespace boost
  522. #endif // BOOST_MULTI_ARRAY_REF_RG071801_HPP