xstrided_view.hpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * Copyright (c) QuantStack *
  4. * *
  5. * Distributed under the terms of the BSD 3-Clause License. *
  6. * *
  7. * The full license is in the file LICENSE, distributed with this software. *
  8. ****************************************************************************/
  9. #ifndef XTENSOR_STRIDED_VIEW_HPP
  10. #define XTENSOR_STRIDED_VIEW_HPP
  11. #include <algorithm>
  12. #include <cstddef>
  13. #include <tuple>
  14. #include <type_traits>
  15. #include <utility>
  16. #include <xtl/xsequence.hpp>
  17. #include <xtl/xvariant.hpp>
  18. #include "xexpression.hpp"
  19. #include "xiterable.hpp"
  20. #include "xlayout.hpp"
  21. #include "xsemantic.hpp"
  22. #include "xstorage.hpp"
  23. #include "xstrided_view_base.hpp"
  24. #include "xutils.hpp"
  25. namespace xt
  26. {
  27. /***************************
  28. * xstrided_view extension *
  29. ***************************/
  30. namespace extension
  31. {
  32. template <class Tag, class CT, class S, layout_type L, class FST>
  33. struct xstrided_view_base_impl;
  34. template <class CT, class S, layout_type L, class FST>
  35. struct xstrided_view_base_impl<xtensor_expression_tag, CT, S, L, FST>
  36. {
  37. using type = xtensor_empty_base;
  38. };
  39. template <class CT, class S, layout_type L, class FST>
  40. struct xstrided_view_base : xstrided_view_base_impl<xexpression_tag_t<CT>, CT, S, L, FST>
  41. {
  42. };
  43. template <class CT, class S, layout_type L, class FST>
  44. using xstrided_view_base_t = typename xstrided_view_base<CT, S, L, FST>::type;
  45. }
  46. template <layout_type L1, layout_type L2, class T>
  47. struct select_iterable_base
  48. {
  49. using type = std::conditional_t<L1 == L2 && L1 != layout_type::dynamic, xcontiguous_iterable<T>, xiterable<T>>;
  50. };
  51. template <layout_type L1, layout_type L2, class T>
  52. using select_iterable_base_t = typename select_iterable_base<L1, L2, T>::type;
  53. template <class CT, class S, layout_type L, class FST>
  54. class xstrided_view;
  55. template <class CT, class S, layout_type L, class FST>
  56. struct xcontainer_inner_types<xstrided_view<CT, S, L, FST>>
  57. {
  58. using xexpression_type = std::decay_t<CT>;
  59. using undecay_expression = CT;
  60. using reference = inner_reference_t<undecay_expression>;
  61. using const_reference = typename xexpression_type::const_reference;
  62. using size_type = typename xexpression_type::size_type;
  63. using shape_type = std::decay_t<S>;
  64. using undecay_shape = S;
  65. using storage_getter = FST;
  66. using inner_storage_type = typename storage_getter::type;
  67. using temporary_type = typename detail::xtype_for_shape<
  68. S>::template type<typename xexpression_type::value_type, xexpression_type::static_layout>;
  69. using storage_type = std::remove_reference_t<inner_storage_type>;
  70. static constexpr layout_type layout = L;
  71. };
  72. template <class CT, class S, layout_type L, class FST>
  73. struct xiterable_inner_types<xstrided_view<CT, S, L, FST>>
  74. {
  75. using inner_shape_type = std::decay_t<S>;
  76. using inner_strides_type = get_strides_t<inner_shape_type>;
  77. using inner_backstrides_type_type = inner_strides_type;
  78. using const_stepper = std::conditional_t<
  79. is_indexed_stepper<typename std::decay_t<CT>::stepper>::value,
  80. xindexed_stepper<const xstrided_view<CT, S, L, FST>, true>,
  81. xstepper<const xstrided_view<CT, S, L, FST>>>;
  82. using stepper = std::conditional_t<
  83. is_indexed_stepper<typename std::decay_t<CT>::stepper>::value,
  84. xindexed_stepper<xstrided_view<CT, S, L, FST>, false>,
  85. xstepper<xstrided_view<CT, S, L, FST>>>;
  86. };
  87. template <class CT, class S, layout_type L, class FST, class RHS>
  88. struct can_assign<xstrided_view<CT, S, L, FST>, RHS> : can_assign<CT, RHS>
  89. {
  90. };
  91. /*****************
  92. * xstrided_view *
  93. *****************/
  94. /**
  95. * @class xstrided_view
  96. * @brief View of an xexpression using strides
  97. *
  98. * The xstrided_view class implements a view utilizing an initial offset
  99. * and strides.
  100. *
  101. * @tparam CT the closure type of the \ref xexpression type underlying this view
  102. * @tparam L the layout of the strided view
  103. * @tparam S the strides type of the strided view
  104. * @tparam FST the flat storage type used for the strided view
  105. *
  106. * @sa strided_view, transpose
  107. */
  108. template <class CT, class S, layout_type L = layout_type::dynamic, class FST = detail::flat_storage_getter<CT, XTENSOR_DEFAULT_TRAVERSAL>>
  109. class xstrided_view
  110. : public xview_semantic<xstrided_view<CT, S, L, FST>>,
  111. public select_iterable_base_t<L, std::decay_t<CT>::static_layout, xstrided_view<CT, S, L, FST>>,
  112. private xstrided_view_base<xstrided_view<CT, S, L, FST>>,
  113. public extension::xstrided_view_base_t<CT, S, L, FST>
  114. {
  115. public:
  116. using self_type = xstrided_view<CT, S, L, FST>;
  117. using base_type = xstrided_view_base<self_type>;
  118. using semantic_base = xview_semantic<self_type>;
  119. using extension_base = extension::xstrided_view_base_t<CT, S, L, FST>;
  120. using expression_tag = typename extension_base::expression_tag;
  121. using xexpression_type = typename base_type::xexpression_type;
  122. using base_type::is_const;
  123. using value_type = typename base_type::value_type;
  124. using reference = typename base_type::reference;
  125. using const_reference = typename base_type::const_reference;
  126. using pointer = typename base_type::pointer;
  127. using const_pointer = typename base_type::const_pointer;
  128. using size_type = typename base_type::size_type;
  129. using difference_type = typename base_type::difference_type;
  130. using inner_storage_type = typename base_type::inner_storage_type;
  131. using storage_type = typename base_type::storage_type;
  132. using linear_iterator = typename storage_type::iterator;
  133. using const_linear_iterator = typename storage_type::const_iterator;
  134. using reverse_linear_iterator = std::reverse_iterator<linear_iterator>;
  135. using const_reverse_linear_iterator = std::reverse_iterator<const_linear_iterator>;
  136. using iterable_base = select_iterable_base_t<L, xexpression_type::static_layout, self_type>;
  137. using inner_shape_type = typename base_type::inner_shape_type;
  138. using inner_strides_type = typename base_type::inner_strides_type;
  139. using inner_backstrides_type = typename base_type::inner_backstrides_type;
  140. using shape_type = typename base_type::shape_type;
  141. using strides_type = typename base_type::strides_type;
  142. using backstrides_type = typename base_type::backstrides_type;
  143. using stepper = typename iterable_base::stepper;
  144. using const_stepper = typename iterable_base::const_stepper;
  145. using base_type::contiguous_layout;
  146. using base_type::static_layout;
  147. using temporary_type = typename xcontainer_inner_types<self_type>::temporary_type;
  148. using base_index_type = xindex_type_t<shape_type>;
  149. using data_alignment = xt_simd::container_alignment_t<storage_type>;
  150. using simd_type = xt_simd::simd_type<value_type>;
  151. using simd_value_type = xt_simd::simd_type<value_type>;
  152. using bool_load_type = typename base_type::bool_load_type;
  153. template <class CTA, class SA>
  154. xstrided_view(CTA&& e, SA&& shape, strides_type&& strides, std::size_t offset, layout_type layout) noexcept;
  155. xstrided_view(const xstrided_view& rhs) = default;
  156. self_type& operator=(const self_type&);
  157. template <class E>
  158. self_type& operator=(const xexpression<E>& e);
  159. template <class E>
  160. disable_xexpression<E, self_type>& operator=(const E& e);
  161. using base_type::backstrides;
  162. using base_type::dimension;
  163. using base_type::is_contiguous;
  164. using base_type::layout;
  165. using base_type::shape;
  166. using base_type::size;
  167. using base_type::strides;
  168. using base_type::operator();
  169. using base_type::at;
  170. using base_type::unchecked;
  171. using base_type::operator[];
  172. using base_type::data;
  173. using base_type::data_offset;
  174. using base_type::element;
  175. using base_type::expression;
  176. using base_type::storage;
  177. using base_type::broadcast_shape;
  178. using base_type::has_linear_assign;
  179. template <class T>
  180. void fill(const T& value);
  181. linear_iterator linear_begin();
  182. linear_iterator linear_end();
  183. const_linear_iterator linear_begin() const;
  184. const_linear_iterator linear_end() const;
  185. const_linear_iterator linear_cbegin() const;
  186. const_linear_iterator linear_cend() const;
  187. reverse_linear_iterator linear_rbegin();
  188. reverse_linear_iterator linear_rend();
  189. const_reverse_linear_iterator linear_rbegin() const;
  190. const_reverse_linear_iterator linear_rend() const;
  191. const_reverse_linear_iterator linear_crbegin() const;
  192. const_reverse_linear_iterator linear_crend() const;
  193. template <class ST, class STEP = stepper>
  194. disable_indexed_stepper_t<STEP> stepper_begin(const ST& shape);
  195. template <class ST, class STEP = stepper>
  196. disable_indexed_stepper_t<STEP> stepper_end(const ST& shape, layout_type l);
  197. template <class ST, class STEP = stepper>
  198. enable_indexed_stepper_t<STEP> stepper_begin(const ST& shape);
  199. template <class ST, class STEP = stepper>
  200. enable_indexed_stepper_t<STEP> stepper_end(const ST& shape, layout_type l);
  201. template <class ST, class STEP = const_stepper>
  202. disable_indexed_stepper_t<STEP> stepper_begin(const ST& shape) const;
  203. template <class ST, class STEP = const_stepper>
  204. disable_indexed_stepper_t<STEP> stepper_end(const ST& shape, layout_type l) const;
  205. template <class ST, class STEP = const_stepper>
  206. enable_indexed_stepper_t<STEP> stepper_begin(const ST& shape) const;
  207. template <class ST, class STEP = const_stepper>
  208. enable_indexed_stepper_t<STEP> stepper_end(const ST& shape, layout_type l) const;
  209. template <class requested_type>
  210. using simd_return_type = xt_simd::simd_return_type<value_type, requested_type>;
  211. template <class T, class R>
  212. using enable_simd_interface = std::enable_if_t<has_simd_interface<T>::value && L != layout_type::dynamic, R>;
  213. template <class align, class simd, class T = xexpression_type>
  214. enable_simd_interface<T, void> store_simd(size_type i, const simd& e);
  215. template <
  216. class align,
  217. class requested_type = value_type,
  218. std::size_t N = xt_simd::simd_traits<requested_type>::size,
  219. class T = xexpression_type>
  220. enable_simd_interface<T, simd_return_type<requested_type>> load_simd(size_type i) const;
  221. reference data_element(size_type i);
  222. const_reference data_element(size_type i) const;
  223. reference flat(size_type i);
  224. const_reference flat(size_type i) const;
  225. using container_iterator = std::
  226. conditional_t<is_const, typename storage_type::const_iterator, typename storage_type::iterator>;
  227. using const_container_iterator = typename storage_type::const_iterator;
  228. template <class E>
  229. using rebind_t = xstrided_view<E, S, L, typename FST::template rebind_t<E>>;
  230. template <class E>
  231. rebind_t<E> build_view(E&& e) const;
  232. private:
  233. container_iterator data_xbegin() noexcept;
  234. const_container_iterator data_xbegin() const noexcept;
  235. container_iterator data_xend(layout_type l, size_type offset) noexcept;
  236. const_container_iterator data_xend(layout_type l, size_type offset) const noexcept;
  237. template <class It>
  238. It data_xbegin_impl(It begin) const noexcept;
  239. template <class It>
  240. It data_xend_impl(It end, layout_type l, size_type offset) const noexcept;
  241. void assign_temporary_impl(temporary_type&& tmp);
  242. using base_type::set_offset;
  243. template <class C>
  244. friend class xstepper;
  245. friend class xview_semantic<self_type>;
  246. friend class xaccessible<self_type>;
  247. friend class xconst_accessible<self_type>;
  248. template <class D>
  249. friend class xaxis_iterator;
  250. template <class D>
  251. friend class xaxis_slice_iterator;
  252. };
  253. /**************************
  254. * xstrided_view builders *
  255. **************************/
  256. template <class T>
  257. using xstrided_slice = xtl::variant<
  258. T,
  259. xrange_adaptor<placeholders::xtuph, T, T>,
  260. xrange_adaptor<T, placeholders::xtuph, T>,
  261. xrange_adaptor<T, T, placeholders::xtuph>,
  262. xrange_adaptor<T, placeholders::xtuph, placeholders::xtuph>,
  263. xrange_adaptor<placeholders::xtuph, T, placeholders::xtuph>,
  264. xrange_adaptor<placeholders::xtuph, placeholders::xtuph, T>,
  265. xrange_adaptor<T, T, T>,
  266. xrange_adaptor<placeholders::xtuph, placeholders::xtuph, placeholders::xtuph>,
  267. xrange<T>,
  268. xstepped_range<T>,
  269. xall_tag,
  270. xellipsis_tag,
  271. xnewaxis_tag>;
  272. /**
  273. * @typedef xstrided_slice_vector
  274. * @brief vector of slices used to build a `xstrided_view`
  275. */
  276. using xstrided_slice_vector = std::vector<xstrided_slice<std::ptrdiff_t>>;
  277. template <layout_type L = layout_type::dynamic, class E, class S, class X>
  278. auto strided_view(E&& e, S&& shape, X&& stride, std::size_t offset = 0, layout_type layout = L) noexcept;
  279. template <class E>
  280. auto strided_view(E&& e, const xstrided_slice_vector& slices);
  281. /********************************
  282. * xstrided_view implementation *
  283. ********************************/
  284. /**
  285. * @name Constructor
  286. */
  287. //@{
  288. /**
  289. * Constructs an xstrided_view
  290. *
  291. * @param e the underlying xexpression for this view
  292. * @param shape the shape of the view
  293. * @param strides the strides of the view
  294. * @param offset the offset of the first element in the underlying container
  295. * @param layout the layout of the view
  296. */
  297. template <class CT, class S, layout_type L, class FST>
  298. template <class CTA, class SA>
  299. inline xstrided_view<CT, S, L, FST>::xstrided_view(
  300. CTA&& e,
  301. SA&& shape,
  302. strides_type&& strides,
  303. std::size_t offset,
  304. layout_type layout
  305. ) noexcept
  306. : base_type(std::forward<CTA>(e), std::forward<SA>(shape), std::move(strides), offset, layout)
  307. {
  308. }
  309. //@}
  310. template <class CT, class S, layout_type L, class FST>
  311. inline auto xstrided_view<CT, S, L, FST>::operator=(const self_type& rhs) -> self_type&
  312. {
  313. temporary_type tmp(rhs);
  314. return this->assign_temporary(std::move(tmp));
  315. }
  316. /**
  317. * @name Extended copy semantic
  318. */
  319. //@{
  320. /**
  321. * The extended assignment operator.
  322. */
  323. template <class CT, class S, layout_type L, class FST>
  324. template <class E>
  325. inline auto xstrided_view<CT, S, L, FST>::operator=(const xexpression<E>& e) -> self_type&
  326. {
  327. return semantic_base::operator=(e);
  328. }
  329. //@}
  330. template <class CT, class S, layout_type L, class FST>
  331. template <class E>
  332. inline auto xstrided_view<CT, S, L, FST>::operator=(const E& e) -> disable_xexpression<E, self_type>&
  333. {
  334. this->fill(e);
  335. return *this;
  336. }
  337. namespace xstrided_view_detail
  338. {
  339. template <class V, class T>
  340. inline void run_assign_temporary_impl(V& v, const T& t, std::true_type /* enable strided assign */)
  341. {
  342. strided_loop_assigner<true>::run(v, t);
  343. }
  344. template <class V, class T>
  345. inline void
  346. run_assign_temporary_impl(V& v, const T& t, std::false_type /* fallback to iterator assign */)
  347. {
  348. std::copy(t.cbegin(), t.cend(), v.begin());
  349. }
  350. }
  351. template <class CT, class S, layout_type L, class FST>
  352. inline void xstrided_view<CT, S, L, FST>::assign_temporary_impl(temporary_type&& tmp)
  353. {
  354. constexpr bool
  355. fast_assign = xassign_traits<xstrided_view<CT, S, L, FST>, temporary_type>::simd_strided_assign();
  356. xstrided_view_detail::run_assign_temporary_impl(*this, tmp, std::integral_constant<bool, fast_assign>{});
  357. }
  358. /**
  359. * @name Data
  360. */
  361. //@{
  362. /**
  363. * Fills the view with the given value.
  364. * @param value the value to fill the view with.
  365. */
  366. template <class CT, class S, layout_type L, class FST>
  367. template <class T>
  368. inline void xstrided_view<CT, S, L, FST>::fill(const T& value)
  369. {
  370. if (layout() != layout_type::dynamic)
  371. {
  372. std::fill(this->linear_begin(), this->linear_end(), value);
  373. }
  374. else
  375. {
  376. std::fill(this->begin(), this->end(), value);
  377. }
  378. }
  379. //@}
  380. template <class CT, class S, layout_type L, class FST>
  381. inline auto xstrided_view<CT, S, L, FST>::data_element(size_type i) -> reference
  382. {
  383. return storage()[i];
  384. }
  385. template <class CT, class S, layout_type L, class FST>
  386. inline auto xstrided_view<CT, S, L, FST>::data_element(size_type i) const -> const_reference
  387. {
  388. return storage()[i];
  389. }
  390. template <class CT, class S, layout_type L, class FST>
  391. inline auto xstrided_view<CT, S, L, FST>::flat(size_type i) -> reference
  392. {
  393. return storage()[i];
  394. }
  395. template <class CT, class S, layout_type L, class FST>
  396. inline auto xstrided_view<CT, S, L, FST>::flat(size_type i) const -> const_reference
  397. {
  398. return storage()[i];
  399. }
  400. template <class CT, class S, layout_type L, class FST>
  401. inline auto xstrided_view<CT, S, L, FST>::linear_begin() -> linear_iterator
  402. {
  403. return this->storage().begin() + static_cast<std::ptrdiff_t>(data_offset());
  404. }
  405. template <class CT, class S, layout_type L, class FST>
  406. inline auto xstrided_view<CT, S, L, FST>::linear_end() -> linear_iterator
  407. {
  408. return this->storage().begin() + static_cast<std::ptrdiff_t>(data_offset() + size());
  409. }
  410. template <class CT, class S, layout_type L, class FST>
  411. inline auto xstrided_view<CT, S, L, FST>::linear_begin() const -> const_linear_iterator
  412. {
  413. return this->linear_cbegin();
  414. }
  415. template <class CT, class S, layout_type L, class FST>
  416. inline auto xstrided_view<CT, S, L, FST>::linear_end() const -> const_linear_iterator
  417. {
  418. return this->linear_cend();
  419. }
  420. template <class CT, class S, layout_type L, class FST>
  421. inline auto xstrided_view<CT, S, L, FST>::linear_cbegin() const -> const_linear_iterator
  422. {
  423. return this->storage().cbegin() + static_cast<std::ptrdiff_t>(data_offset());
  424. }
  425. template <class CT, class S, layout_type L, class FST>
  426. inline auto xstrided_view<CT, S, L, FST>::linear_cend() const -> const_linear_iterator
  427. {
  428. return this->storage().cbegin() + static_cast<std::ptrdiff_t>(data_offset() + size());
  429. }
  430. template <class CT, class S, layout_type L, class FST>
  431. inline auto xstrided_view<CT, S, L, FST>::linear_rbegin() -> reverse_linear_iterator
  432. {
  433. return reverse_linear_iterator(this->linear_begin());
  434. }
  435. template <class CT, class S, layout_type L, class FST>
  436. inline auto xstrided_view<CT, S, L, FST>::linear_rend() -> reverse_linear_iterator
  437. {
  438. return reverse_linear_iterator(this->linear_end());
  439. }
  440. template <class CT, class S, layout_type L, class FST>
  441. inline auto xstrided_view<CT, S, L, FST>::linear_rbegin() const -> const_reverse_linear_iterator
  442. {
  443. return this->linear_crbegin();
  444. }
  445. template <class CT, class S, layout_type L, class FST>
  446. inline auto xstrided_view<CT, S, L, FST>::linear_rend() const -> const_reverse_linear_iterator
  447. {
  448. return this->linear_crend();
  449. }
  450. template <class CT, class S, layout_type L, class FST>
  451. inline auto xstrided_view<CT, S, L, FST>::linear_crbegin() const -> const_reverse_linear_iterator
  452. {
  453. return const_reverse_linear_iterator(this->linear_cbegin());
  454. }
  455. template <class CT, class S, layout_type L, class FST>
  456. inline auto xstrided_view<CT, S, L, FST>::linear_crend() const -> const_reverse_linear_iterator
  457. {
  458. return const_reverse_linear_iterator(this->linear_cend());
  459. }
  460. /***************
  461. * stepper api *
  462. ***************/
  463. template <class CT, class S, layout_type L, class FST>
  464. template <class ST, class STEP>
  465. inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) -> disable_indexed_stepper_t<STEP>
  466. {
  467. size_type offset = shape.size() - dimension();
  468. return stepper(this, data_xbegin(), offset);
  469. }
  470. template <class CT, class S, layout_type L, class FST>
  471. template <class ST, class STEP>
  472. inline auto xstrided_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type l)
  473. -> disable_indexed_stepper_t<STEP>
  474. {
  475. size_type offset = shape.size() - dimension();
  476. return stepper(this, data_xend(l, offset), offset);
  477. }
  478. template <class CT, class S, layout_type L, class FST>
  479. template <class ST, class STEP>
  480. inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) -> enable_indexed_stepper_t<STEP>
  481. {
  482. size_type offset = shape.size() - dimension();
  483. return stepper(this, offset);
  484. }
  485. template <class CT, class S, layout_type L, class FST>
  486. template <class ST, class STEP>
  487. inline auto xstrided_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type /*l*/)
  488. -> enable_indexed_stepper_t<STEP>
  489. {
  490. size_type offset = shape.size() - dimension();
  491. return stepper(this, offset, true);
  492. }
  493. template <class CT, class S, layout_type L, class FST>
  494. template <class ST, class STEP>
  495. inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) const
  496. -> disable_indexed_stepper_t<STEP>
  497. {
  498. size_type offset = shape.size() - dimension();
  499. return const_stepper(this, data_xbegin(), offset);
  500. }
  501. template <class CT, class S, layout_type L, class FST>
  502. template <class ST, class STEP>
  503. inline auto xstrided_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type l) const
  504. -> disable_indexed_stepper_t<STEP>
  505. {
  506. size_type offset = shape.size() - dimension();
  507. return const_stepper(this, data_xend(l, offset), offset);
  508. }
  509. template <class CT, class S, layout_type L, class FST>
  510. template <class ST, class STEP>
  511. inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) const
  512. -> enable_indexed_stepper_t<STEP>
  513. {
  514. size_type offset = shape.size() - dimension();
  515. return const_stepper(this, offset);
  516. }
  517. template <class CT, class S, layout_type L, class FST>
  518. template <class ST, class STEP>
  519. inline auto xstrided_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type /*l*/) const
  520. -> enable_indexed_stepper_t<STEP>
  521. {
  522. size_type offset = shape.size() - dimension();
  523. return const_stepper(this, offset, true);
  524. }
  525. template <class CT, class S, layout_type L, class FST>
  526. template <class It>
  527. inline It xstrided_view<CT, S, L, FST>::data_xbegin_impl(It begin) const noexcept
  528. {
  529. return begin + static_cast<std::ptrdiff_t>(this->data_offset());
  530. }
  531. template <class CT, class S, layout_type L, class FST>
  532. template <class It>
  533. inline It
  534. xstrided_view<CT, S, L, FST>::data_xend_impl(It begin, layout_type l, size_type offset) const noexcept
  535. {
  536. return strided_data_end(*this, begin + std::ptrdiff_t(this->data_offset()), l, offset);
  537. }
  538. template <class CT, class S, layout_type L, class FST>
  539. inline auto xstrided_view<CT, S, L, FST>::data_xbegin() noexcept -> container_iterator
  540. {
  541. return data_xbegin_impl(this->storage().begin());
  542. }
  543. template <class CT, class S, layout_type L, class FST>
  544. inline auto xstrided_view<CT, S, L, FST>::data_xbegin() const noexcept -> const_container_iterator
  545. {
  546. return data_xbegin_impl(this->storage().cbegin());
  547. }
  548. template <class CT, class S, layout_type L, class FST>
  549. inline auto xstrided_view<CT, S, L, FST>::data_xend(layout_type l, size_type offset) noexcept
  550. -> container_iterator
  551. {
  552. return data_xend_impl(this->storage().begin(), l, offset);
  553. }
  554. template <class CT, class S, layout_type L, class FST>
  555. inline auto xstrided_view<CT, S, L, FST>::data_xend(layout_type l, size_type offset) const noexcept
  556. -> const_container_iterator
  557. {
  558. return data_xend_impl(this->storage().cbegin(), l, offset);
  559. }
  560. template <class CT, class S, layout_type L, class FST>
  561. template <class alignment, class simd, class T>
  562. inline auto xstrided_view<CT, S, L, FST>::store_simd(size_type i, const simd& e)
  563. -> enable_simd_interface<T, void>
  564. {
  565. using align_mode = driven_align_mode_t<alignment, data_alignment>;
  566. xt_simd::store_as(&(storage()[i]), e, align_mode());
  567. }
  568. template <class CT, class S, layout_type L, class FST>
  569. template <class alignment, class requested_type, std::size_t N, class T>
  570. inline auto xstrided_view<CT, S, L, FST>::load_simd(size_type i) const
  571. -> enable_simd_interface<T, simd_return_type<requested_type>>
  572. {
  573. using align_mode = driven_align_mode_t<alignment, data_alignment>;
  574. return xt_simd::load_as<requested_type>(&(storage()[i]), align_mode());
  575. }
  576. template <class CT, class S, layout_type L, class FST>
  577. template <class E>
  578. inline auto xstrided_view<CT, S, L, FST>::build_view(E&& e) const -> rebind_t<E>
  579. {
  580. inner_shape_type sh(this->shape());
  581. inner_strides_type str(this->strides());
  582. return rebind_t<E>(
  583. std::forward<E>(e),
  584. std::move(sh),
  585. std::move(str),
  586. base_type::data_offset(),
  587. this->layout()
  588. );
  589. }
  590. /*****************************************
  591. * xstrided_view builders implementation *
  592. *****************************************/
  593. /**
  594. * Construct a strided view from an xexpression, shape, strides and offset.
  595. *
  596. * @param e xexpression
  597. * @param shape the shape of the view
  598. * @param strides the new strides of the view
  599. * @param offset the offset of the first element in the underlying container
  600. * @param layout the new layout of the expression
  601. *
  602. * @tparam L the static layout type of the view (default: dynamic)
  603. * @tparam E type of xexpression
  604. * @tparam S strides type
  605. * @tparam X strides type
  606. *
  607. * @return the view
  608. */
  609. template <layout_type L, class E, class S, class X>
  610. inline auto strided_view(E&& e, S&& shape, X&& strides, std::size_t offset, layout_type layout) noexcept
  611. {
  612. using view_type = xstrided_view<xclosure_t<E>, S, L>;
  613. return view_type(std::forward<E>(e), std::forward<S>(shape), std::forward<X>(strides), offset, layout);
  614. }
  615. namespace detail
  616. {
  617. struct no_adj_strides_policy
  618. {
  619. protected:
  620. inline void resize(std::size_t)
  621. {
  622. }
  623. inline void set_fake_slice(std::size_t)
  624. {
  625. }
  626. template <class ST, class S>
  627. bool fill_args(
  628. const xstrided_slice_vector& /*slices*/,
  629. std::size_t /*sl_idx*/,
  630. std::size_t /*i*/,
  631. std::size_t /*old_shape*/,
  632. const ST& /*old_stride*/,
  633. S& /*shape*/,
  634. get_strides_t<S>& /*strides*/
  635. )
  636. {
  637. return false;
  638. }
  639. };
  640. }
  641. /**
  642. * Function to create a dynamic view from
  643. * an xexpression and an xstrided_slice_vector.
  644. *
  645. * @param e xexpression
  646. * @param slices the slice vector
  647. *
  648. * @return initialized strided_view according to slices
  649. *
  650. * @code{.cpp}
  651. * xt::xarray<double> a = {{1, 2, 3}, {4, 5, 6}};
  652. * xt::xstrided_slice_vector sv({xt::range(0, 1)});
  653. * sv.push_back(xt::range(0, 3, 2));
  654. * auto v = xt::strided_view(a, sv);
  655. * // ==> {{1, 3}}
  656. * @endcode
  657. *
  658. * You can also achieve the same with the following short-hand syntax:
  659. *
  660. * @code{.cpp}
  661. * xt::xarray<double> a = {{1, 2, 3}, {4, 5, 6}};
  662. * auto v = xt::strided_view(a, {xt::range(0, 1), xt::range(0, 3, 2)});
  663. * // ==> {{1, 3}}
  664. * @endcode
  665. */
  666. template <class E>
  667. inline auto strided_view(E&& e, const xstrided_slice_vector& slices)
  668. {
  669. detail::strided_view_args<detail::no_adj_strides_policy> args;
  670. args.fill_args(
  671. e.shape(),
  672. detail::get_strides<XTENSOR_DEFAULT_TRAVERSAL>(e),
  673. detail::get_offset<XTENSOR_DEFAULT_TRAVERSAL>(e),
  674. e.layout(),
  675. slices
  676. );
  677. using view_type = xstrided_view<xclosure_t<E>, decltype(args.new_shape)>;
  678. return view_type(
  679. std::forward<E>(e),
  680. std::move(args.new_shape),
  681. std::move(args.new_strides),
  682. args.new_offset,
  683. args.new_layout
  684. );
  685. }
  686. namespace detail
  687. {
  688. template <typename S>
  689. struct rebind_shape;
  690. template <std::size_t... X>
  691. struct rebind_shape<xt::fixed_shape<X...>>
  692. {
  693. using type = xt::fixed_shape<X...>;
  694. };
  695. template <class S>
  696. struct rebind_shape
  697. {
  698. using type = rebind_container_t<size_t, S>;
  699. };
  700. template <
  701. class S,
  702. std::enable_if_t<std::is_signed<get_value_type_t<typename std::decay<S>::type>>::value, bool> = true>
  703. inline void recalculate_shape_impl(S& shape, size_t size)
  704. {
  705. using value_type = get_value_type_t<typename std::decay_t<S>>;
  706. XTENSOR_ASSERT(std::count(shape.cbegin(), shape.cend(), -1) <= 1);
  707. auto iter = std::find(shape.begin(), shape.end(), -1);
  708. if (iter != std::end(shape))
  709. {
  710. const auto total = std::accumulate(shape.cbegin(), shape.cend(), -1, std::multiplies<int>{});
  711. const auto missing_dimension = size / total;
  712. (*iter) = static_cast<value_type>(missing_dimension);
  713. }
  714. }
  715. template <
  716. class S,
  717. std::enable_if_t<!std::is_signed<get_value_type_t<typename std::decay<S>::type>>::value, bool> = true>
  718. inline void recalculate_shape_impl(S&, size_t)
  719. {
  720. }
  721. template <class S>
  722. inline auto recalculate_shape(S&& shape, size_t size)
  723. {
  724. return recalculate_shape_impl(shape, size);
  725. }
  726. }
  727. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class S>
  728. inline auto reshape_view(E&& e, S&& shape)
  729. {
  730. static_assert(
  731. L == layout_type::row_major || L == layout_type::column_major,
  732. "traversal has to be row or column major"
  733. );
  734. using shape_type = std::decay_t<decltype(shape)>;
  735. using unsigned_shape_type = typename detail::rebind_shape<shape_type>::type;
  736. get_strides_t<unsigned_shape_type> strides;
  737. detail::recalculate_shape(shape, e.size());
  738. xt::resize_container(strides, shape.size());
  739. compute_strides(shape, L, strides);
  740. constexpr auto computed_layout = std::decay_t<E>::static_layout == L ? L : layout_type::dynamic;
  741. using view_type = xstrided_view<
  742. xclosure_t<E>,
  743. unsigned_shape_type,
  744. computed_layout,
  745. detail::flat_adaptor_getter<xclosure_t<E>, L>>;
  746. return view_type(
  747. std::forward<E>(e),
  748. xtl::forward_sequence<unsigned_shape_type, S>(shape),
  749. std::move(strides),
  750. 0,
  751. e.layout()
  752. );
  753. }
  754. /**
  755. * @deprecated
  756. * @brief Return a view on a container with a new shape
  757. *
  758. * Note: if you resize the underlying container, this view becomes
  759. * invalidated.
  760. *
  761. * @param e xexpression to reshape
  762. * @param shape new shape
  763. * @param order traversal order (optional)
  764. *
  765. * @return view on xexpression with new shape
  766. */
  767. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class S>
  768. inline auto reshape_view(E&& e, S&& shape, layout_type /*order*/)
  769. {
  770. return reshape_view<L>(std::forward<E>(e), std::forward<S>(shape));
  771. }
  772. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class I, std::size_t N>
  773. inline auto reshape_view(E&& e, const I (&shape)[N], layout_type order)
  774. {
  775. using shape_type = std::array<std::size_t, N>;
  776. return reshape_view<L>(std::forward<E>(e), xtl::forward_sequence<shape_type, decltype(shape)>(shape), order);
  777. }
  778. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class I, std::size_t N>
  779. inline auto reshape_view(E&& e, const I (&shape)[N])
  780. {
  781. using shape_type = std::array<I, N>;
  782. return reshape_view<L>(std::forward<E>(e), xtl::forward_sequence<shape_type, decltype(shape)>(shape));
  783. }
  784. }
  785. #endif