xdynamic_view.hpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. /***************************************************************************
  2. * Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * *
  4. * Distributed under the terms of the BSD 3-Clause License. *
  5. * *
  6. * The full license is in the file LICENSE, distributed with this software. *
  7. ****************************************************************************/
  8. #ifndef XTENSOR_DYNAMIC_VIEW_HPP
  9. #define XTENSOR_DYNAMIC_VIEW_HPP
  10. #include <xtl/xsequence.hpp>
  11. #include <xtl/xvariant.hpp>
  12. #include "xexpression.hpp"
  13. #include "xiterable.hpp"
  14. #include "xlayout.hpp"
  15. #include "xsemantic.hpp"
  16. #include "xstrided_view_base.hpp"
  17. namespace xt
  18. {
  19. template <class CT, class S, layout_type L, class FST>
  20. class xdynamic_view;
  21. template <class CT, class S, layout_type L, class FST>
  22. struct xcontainer_inner_types<xdynamic_view<CT, S, L, FST>>
  23. {
  24. using xexpression_type = std::decay_t<CT>;
  25. using undecay_expression = CT;
  26. using reference = inner_reference_t<undecay_expression>;
  27. using const_reference = typename xexpression_type::const_reference;
  28. using size_type = typename xexpression_type::size_type;
  29. using shape_type = std::decay_t<S>;
  30. using undecay_shape = S;
  31. using storage_getter = FST;
  32. using inner_storage_type = typename storage_getter::type;
  33. using temporary_type = xarray<std::decay_t<typename xexpression_type::value_type>, xexpression_type::static_layout>;
  34. static constexpr layout_type layout = L;
  35. };
  36. template <class CT, class S, layout_type L, class FST>
  37. struct xiterable_inner_types<xdynamic_view<CT, S, L, FST>>
  38. {
  39. using inner_shape_type = S;
  40. using inner_strides_type = inner_shape_type;
  41. using inner_backstrides_type = inner_shape_type;
  42. #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ == 8
  43. static constexpr auto
  44. random_instantiation_var_for_gcc8_data_iface = has_data_interface<xdynamic_view<CT, S, L, FST>>::value;
  45. static constexpr auto
  46. random_instantiation_var_for_gcc8_has_strides = has_strides<xdynamic_view<CT, S, L, FST>>::value;
  47. #endif
  48. // TODO: implement efficient stepper specific to the dynamic_view
  49. using const_stepper = xindexed_stepper<const xdynamic_view<CT, S, L, FST>, true>;
  50. using stepper = xindexed_stepper<xdynamic_view<CT, S, L, FST>, false>;
  51. };
  52. /****************************
  53. * xdynamic_view extensions *
  54. ****************************/
  55. namespace extension
  56. {
  57. template <class Tag, class CT, class S, layout_type L, class FST>
  58. struct xdynamic_view_base_impl;
  59. template <class CT, class S, layout_type L, class FST>
  60. struct xdynamic_view_base_impl<xtensor_expression_tag, CT, S, L, FST>
  61. {
  62. using type = xtensor_empty_base;
  63. };
  64. template <class CT, class S, layout_type L, class FST>
  65. struct xdynamic_view_base : xdynamic_view_base_impl<xexpression_tag_t<CT>, CT, S, L, FST>
  66. {
  67. };
  68. template <class CT, class S, layout_type L, class FST>
  69. using xdynamic_view_base_t = typename xdynamic_view_base<CT, S, L, FST>::type;
  70. }
  71. /*****************
  72. * xdynamic_view *
  73. *****************/
  74. namespace detail
  75. {
  76. template <class T>
  77. class xfake_slice;
  78. }
  79. template <class CT, class S, layout_type L = layout_type::dynamic, class FST = detail::flat_storage_getter<CT, XTENSOR_DEFAULT_TRAVERSAL>>
  80. class xdynamic_view : public xview_semantic<xdynamic_view<CT, S, L, FST>>,
  81. public xiterable<xdynamic_view<CT, S, L, FST>>,
  82. public extension::xdynamic_view_base_t<CT, S, L, FST>,
  83. private xstrided_view_base<xdynamic_view<CT, S, L, FST>>
  84. {
  85. public:
  86. using self_type = xdynamic_view<CT, S, L, FST>;
  87. using base_type = xstrided_view_base<self_type>;
  88. using semantic_base = xview_semantic<self_type>;
  89. using extension_base = extension::xdynamic_view_base_t<CT, S, L, FST>;
  90. using expression_tag = typename extension_base::expression_tag;
  91. using xexpression_type = typename base_type::xexpression_type;
  92. using base_type::is_const;
  93. using value_type = typename base_type::value_type;
  94. using reference = typename base_type::reference;
  95. using const_reference = typename base_type::const_reference;
  96. using pointer = typename base_type::pointer;
  97. using const_pointer = typename base_type::const_pointer;
  98. using size_type = typename base_type::size_type;
  99. using difference_type = typename base_type::difference_type;
  100. using inner_storage_type = typename base_type::inner_storage_type;
  101. using storage_type = typename base_type::storage_type;
  102. using iterable_base = xiterable<self_type>;
  103. using inner_shape_type = typename iterable_base::inner_shape_type;
  104. using inner_strides_type = typename base_type::inner_strides_type;
  105. using inner_backstrides_type = typename base_type::inner_backstrides_type;
  106. using shape_type = typename base_type::shape_type;
  107. using strides_type = typename base_type::strides_type;
  108. using backstrides_type = typename base_type::backstrides_type;
  109. using stepper = typename iterable_base::stepper;
  110. using const_stepper = typename iterable_base::const_stepper;
  111. using base_type::contiguous_layout;
  112. using base_type::static_layout;
  113. using temporary_type = typename xcontainer_inner_types<self_type>::temporary_type;
  114. using base_index_type = xindex_type_t<shape_type>;
  115. using simd_value_type = typename base_type::simd_value_type;
  116. using bool_load_type = typename base_type::bool_load_type;
  117. using strides_vt = typename strides_type::value_type;
  118. using slice_type = xtl::variant<detail::xfake_slice<strides_vt>, xkeep_slice<strides_vt>, xdrop_slice<strides_vt>>;
  119. using slice_vector_type = std::vector<slice_type>;
  120. template <class CTA, class SA>
  121. xdynamic_view(
  122. CTA&& e,
  123. SA&& shape,
  124. get_strides_t<S>&& strides,
  125. std::size_t offset,
  126. layout_type layout,
  127. slice_vector_type&& slices,
  128. get_strides_t<S>&& adj_strides
  129. ) noexcept;
  130. template <class E>
  131. self_type& operator=(const xexpression<E>& e);
  132. template <class E>
  133. disable_xexpression<E, self_type>& operator=(const E& e);
  134. using base_type::dimension;
  135. using base_type::is_contiguous;
  136. using base_type::layout;
  137. using base_type::shape;
  138. using base_type::size;
  139. // Explicitly deleting strides method to avoid compilers complaining
  140. // about not being able to call the strides method from xstrided_view_base
  141. // private base
  142. const inner_strides_type& strides() const noexcept = delete;
  143. reference operator()();
  144. const_reference operator()() const;
  145. template <class... Args>
  146. reference operator()(Args... args);
  147. template <class... Args>
  148. const_reference operator()(Args... args) const;
  149. template <class... Args>
  150. reference unchecked(Args... args);
  151. template <class... Args>
  152. const_reference unchecked(Args... args) const;
  153. reference flat(size_type index);
  154. const_reference flat(size_type index) const;
  155. using base_type::operator[];
  156. using base_type::at;
  157. using base_type::back;
  158. using base_type::front;
  159. using base_type::in_bounds;
  160. using base_type::periodic;
  161. template <class It>
  162. reference element(It first, It last);
  163. template <class It>
  164. const_reference element(It first, It last) const;
  165. size_type data_offset() const noexcept;
  166. // Explicitly deleting data methods so has_data_interface results
  167. // to false instead of having compilers complaining about not being
  168. // able to call the methods from the private base
  169. value_type* data() noexcept = delete;
  170. const value_type* data() const noexcept = delete;
  171. using base_type::broadcast_shape;
  172. using base_type::expression;
  173. using base_type::storage;
  174. template <class O>
  175. bool has_linear_assign(const O& str) const noexcept;
  176. template <class T>
  177. void fill(const T& value);
  178. template <class ST>
  179. stepper stepper_begin(const ST& shape);
  180. template <class ST>
  181. stepper stepper_end(const ST& shape, layout_type l);
  182. template <class ST>
  183. const_stepper stepper_begin(const ST& shape) const;
  184. template <class ST>
  185. const_stepper stepper_end(const ST& shape, layout_type l) const;
  186. using container_iterator = std::
  187. conditional_t<is_const, typename storage_type::const_iterator, typename storage_type::iterator>;
  188. using const_container_iterator = typename storage_type::const_iterator;
  189. template <class E>
  190. using rebind_t = xdynamic_view<E, S, L, typename FST::template rebind_t<E>>;
  191. template <class E>
  192. rebind_t<E> build_view(E&& e) const;
  193. private:
  194. using offset_type = typename base_type::offset_type;
  195. slice_vector_type m_slices;
  196. inner_strides_type m_adj_strides;
  197. container_iterator data_xbegin() noexcept;
  198. const_container_iterator data_xbegin() const noexcept;
  199. container_iterator data_xend(layout_type l, size_type offset) noexcept;
  200. const_container_iterator data_xend(layout_type l, size_type offset) const noexcept;
  201. template <class It>
  202. It data_xbegin_impl(It begin) const noexcept;
  203. template <class It>
  204. It data_xend_impl(It end, layout_type l, size_type offset) const noexcept;
  205. void assign_temporary_impl(temporary_type&& tmp);
  206. template <class T, class... Args>
  207. offset_type adjust_offset(offset_type offset, T idx, Args... args) const noexcept;
  208. offset_type adjust_offset(offset_type offset) const noexcept;
  209. template <class T, class... Args>
  210. offset_type
  211. adjust_offset_impl(offset_type offset, size_type idx_offset, T idx, Args... args) const noexcept;
  212. offset_type adjust_offset_impl(offset_type offset, size_type idx_offset) const noexcept;
  213. template <class It>
  214. offset_type adjust_element_offset(offset_type offset, It first, It last) const noexcept;
  215. template <class C>
  216. friend class xstepper;
  217. friend class xview_semantic<self_type>;
  218. friend class xaccessible<self_type>;
  219. friend class xconst_accessible<self_type>;
  220. };
  221. /**************************
  222. * xdynamic_view builders *
  223. **************************/
  224. template <class T>
  225. using xdynamic_slice = xtl::variant<
  226. T,
  227. xrange_adaptor<placeholders::xtuph, T, T>,
  228. xrange_adaptor<T, placeholders::xtuph, T>,
  229. xrange_adaptor<T, T, placeholders::xtuph>,
  230. xrange_adaptor<T, placeholders::xtuph, placeholders::xtuph>,
  231. xrange_adaptor<placeholders::xtuph, T, placeholders::xtuph>,
  232. xrange_adaptor<placeholders::xtuph, placeholders::xtuph, T>,
  233. xrange_adaptor<T, T, T>,
  234. xrange_adaptor<placeholders::xtuph, placeholders::xtuph, placeholders::xtuph>,
  235. xrange<T>,
  236. xstepped_range<T>,
  237. xkeep_slice<T>,
  238. xdrop_slice<T>,
  239. xall_tag,
  240. xellipsis_tag,
  241. xnewaxis_tag>;
  242. using xdynamic_slice_vector = std::vector<xdynamic_slice<std::ptrdiff_t>>;
  243. template <class E>
  244. auto dynamic_view(E&& e, const xdynamic_slice_vector& slices);
  245. /******************************
  246. * xfake_slice implementation *
  247. ******************************/
  248. namespace detail
  249. {
  250. template <class T>
  251. class xfake_slice : public xslice<xfake_slice<T>>
  252. {
  253. public:
  254. using size_type = T;
  255. using self_type = xfake_slice<T>;
  256. xfake_slice() = default;
  257. size_type operator()(size_type /*i*/) const noexcept
  258. {
  259. return size_type(0);
  260. }
  261. size_type size() const noexcept
  262. {
  263. return size_type(1);
  264. }
  265. size_type step_size() const noexcept
  266. {
  267. return size_type(0);
  268. }
  269. size_type step_size(std::size_t /*i*/, std::size_t /*n*/ = 1) const noexcept
  270. {
  271. return size_type(0);
  272. }
  273. size_type revert_index(std::size_t i) const noexcept
  274. {
  275. return i;
  276. }
  277. bool contains(size_type /*i*/) const noexcept
  278. {
  279. return true;
  280. }
  281. bool operator==(const self_type& /*rhs*/) const noexcept
  282. {
  283. return true;
  284. }
  285. bool operator!=(const self_type& /*rhs*/) const noexcept
  286. {
  287. return false;
  288. }
  289. };
  290. }
  291. /********************************
  292. * xdynamic_view implementation *
  293. ********************************/
  294. template <class CT, class S, layout_type L, class FST>
  295. template <class CTA, class SA>
  296. inline xdynamic_view<CT, S, L, FST>::xdynamic_view(
  297. CTA&& e,
  298. SA&& shape,
  299. get_strides_t<S>&& strides,
  300. std::size_t offset,
  301. layout_type layout,
  302. slice_vector_type&& slices,
  303. get_strides_t<S>&& adj_strides
  304. ) noexcept
  305. : base_type(std::forward<CTA>(e), std::forward<SA>(shape), std::move(strides), offset, layout)
  306. , m_slices(std::move(slices))
  307. , m_adj_strides(std::move(adj_strides))
  308. {
  309. }
  310. template <class CT, class S, layout_type L, class FST>
  311. template <class E>
  312. inline auto xdynamic_view<CT, S, L, FST>::operator=(const xexpression<E>& e) -> self_type&
  313. {
  314. return semantic_base::operator=(e);
  315. }
  316. template <class CT, class S, layout_type L, class FST>
  317. template <class E>
  318. inline auto xdynamic_view<CT, S, L, FST>::operator=(const E& e) -> disable_xexpression<E, self_type>&
  319. {
  320. std::fill(this->begin(), this->end(), e);
  321. return *this;
  322. }
  323. template <class CT, class S, layout_type L, class FST>
  324. inline auto xdynamic_view<CT, S, L, FST>::operator()() -> reference
  325. {
  326. return base_type::storage()[data_offset()];
  327. }
  328. template <class CT, class S, layout_type L, class FST>
  329. inline auto xdynamic_view<CT, S, L, FST>::operator()() const -> const_reference
  330. {
  331. return base_type::storage()[data_offset()];
  332. }
  333. template <class CT, class S, layout_type L, class FST>
  334. template <class... Args>
  335. inline auto xdynamic_view<CT, S, L, FST>::operator()(Args... args) -> reference
  336. {
  337. XTENSOR_TRY(check_index(base_type::shape(), args...));
  338. XTENSOR_CHECK_DIMENSION(base_type::shape(), args...);
  339. offset_type offset = base_type::compute_index(args...);
  340. offset = adjust_offset(offset, args...);
  341. return base_type::storage()[static_cast<size_type>(offset)];
  342. }
  343. template <class CT, class S, layout_type L, class FST>
  344. template <class... Args>
  345. inline auto xdynamic_view<CT, S, L, FST>::operator()(Args... args) const -> const_reference
  346. {
  347. XTENSOR_TRY(check_index(base_type::shape(), args...));
  348. XTENSOR_CHECK_DIMENSION(base_type::shape(), args...);
  349. offset_type offset = base_type::compute_index(args...);
  350. offset = adjust_offset(offset, args...);
  351. return base_type::storage()[static_cast<size_type>(offset)];
  352. }
  353. template <class CT, class S, layout_type L, class FST>
  354. template <class O>
  355. inline bool xdynamic_view<CT, S, L, FST>::has_linear_assign(const O&) const noexcept
  356. {
  357. return false;
  358. }
  359. template <class CT, class S, layout_type L, class FST>
  360. template <class... Args>
  361. inline auto xdynamic_view<CT, S, L, FST>::unchecked(Args... args) -> reference
  362. {
  363. offset_type offset = base_type::compute_unchecked_index(args...);
  364. offset = adjust_offset(args...);
  365. return base_type::storage()[static_cast<size_type>(offset)];
  366. }
  367. template <class CT, class S, layout_type L, class FST>
  368. template <class... Args>
  369. inline auto xdynamic_view<CT, S, L, FST>::unchecked(Args... args) const -> const_reference
  370. {
  371. offset_type offset = base_type::compute_unchecked_index(args...);
  372. offset = adjust_offset(args...);
  373. return base_type::storage()[static_cast<size_type>(offset)];
  374. }
  375. template <class CT, class S, layout_type L, class FST>
  376. inline auto xdynamic_view<CT, S, L, FST>::flat(size_type i) -> reference
  377. {
  378. return base_type::storage()[data_offset() + i];
  379. }
  380. template <class CT, class S, layout_type L, class FST>
  381. inline auto xdynamic_view<CT, S, L, FST>::flat(size_type i) const -> const_reference
  382. {
  383. return base_type::storage()[data_offset() + i];
  384. }
  385. template <class CT, class S, layout_type L, class FST>
  386. template <class It>
  387. inline auto xdynamic_view<CT, S, L, FST>::element(It first, It last) -> reference
  388. {
  389. XTENSOR_TRY(check_element_index(base_type::shape(), first, last));
  390. offset_type offset = base_type::compute_element_index(first, last);
  391. offset = adjust_element_offset(offset, first, last);
  392. return base_type::storage()[static_cast<size_type>(offset)];
  393. }
  394. template <class CT, class S, layout_type L, class FST>
  395. template <class It>
  396. inline auto xdynamic_view<CT, S, L, FST>::element(It first, It last) const -> const_reference
  397. {
  398. XTENSOR_TRY(check_element_index(base_type::shape(), first, last));
  399. offset_type offset = base_type::compute_element_index(first, last);
  400. offset = adjust_element_offset(offset, first, last);
  401. return base_type::storage()[static_cast<size_type>(offset)];
  402. }
  403. template <class CT, class S, layout_type L, class FST>
  404. inline auto xdynamic_view<CT, S, L, FST>::data_offset() const noexcept -> size_type
  405. {
  406. size_type offset = base_type::data_offset();
  407. size_type sl_offset = xtl::visit(
  408. [](const auto& sl)
  409. {
  410. return sl(size_type(0));
  411. },
  412. m_slices[0]
  413. );
  414. return offset + sl_offset * m_adj_strides[0];
  415. }
  416. template <class CT, class S, layout_type L, class FST>
  417. template <class T>
  418. inline void xdynamic_view<CT, S, L, FST>::fill(const T& value)
  419. {
  420. return std::fill(this->linear_begin(), this->linear_end(), value);
  421. }
  422. template <class CT, class S, layout_type L, class FST>
  423. template <class ST>
  424. inline auto xdynamic_view<CT, S, L, FST>::stepper_begin(const ST& shape) -> stepper
  425. {
  426. size_type offset = shape.size() - dimension();
  427. return stepper(this, offset);
  428. }
  429. template <class CT, class S, layout_type L, class FST>
  430. template <class ST>
  431. inline auto xdynamic_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type /*l*/) -> stepper
  432. {
  433. size_type offset = shape.size() - dimension();
  434. return stepper(this, offset, true);
  435. }
  436. template <class CT, class S, layout_type L, class FST>
  437. template <class ST>
  438. inline auto xdynamic_view<CT, S, L, FST>::stepper_begin(const ST& shape) const -> const_stepper
  439. {
  440. size_type offset = shape.size() - dimension();
  441. return const_stepper(this, offset);
  442. }
  443. template <class CT, class S, layout_type L, class FST>
  444. template <class ST>
  445. inline auto xdynamic_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type /*l*/) const
  446. -> const_stepper
  447. {
  448. size_type offset = shape.size() - dimension();
  449. return const_stepper(this, offset, true);
  450. }
  451. template <class CT, class S, layout_type L, class FST>
  452. template <class E>
  453. inline auto xdynamic_view<CT, S, L, FST>::build_view(E&& e) const -> rebind_t<E>
  454. {
  455. inner_shape_type sh(this->shape());
  456. inner_strides_type str(base_type::strides());
  457. slice_vector_type svt(m_slices);
  458. inner_strides_type adj_str(m_adj_strides);
  459. return rebind_t<E>(
  460. std::forward<E>(e),
  461. std::move(sh),
  462. std::move(str),
  463. base_type::data_offset(),
  464. this->layout(),
  465. std::move(svt),
  466. std::move(adj_str)
  467. );
  468. }
  469. template <class CT, class S, layout_type L, class FST>
  470. inline auto xdynamic_view<CT, S, L, FST>::data_xbegin() noexcept -> container_iterator
  471. {
  472. return data_xbegin_impl(this->storage().begin());
  473. }
  474. template <class CT, class S, layout_type L, class FST>
  475. inline auto xdynamic_view<CT, S, L, FST>::data_xbegin() const noexcept -> const_container_iterator
  476. {
  477. return data_xbegin_impl(this->storage().cbegin());
  478. }
  479. template <class CT, class S, layout_type L, class FST>
  480. inline auto xdynamic_view<CT, S, L, FST>::data_xend(layout_type l, size_type offset) noexcept
  481. -> container_iterator
  482. {
  483. return data_xend_impl(this->storage().begin(), l, offset);
  484. }
  485. template <class CT, class S, layout_type L, class FST>
  486. inline auto xdynamic_view<CT, S, L, FST>::data_xend(layout_type l, size_type offset) const noexcept
  487. -> const_container_iterator
  488. {
  489. return data_xend_impl(this->storage().cbegin(), l, offset);
  490. }
  491. template <class CT, class S, layout_type L, class FST>
  492. template <class It>
  493. inline It xdynamic_view<CT, S, L, FST>::data_xbegin_impl(It begin) const noexcept
  494. {
  495. return begin + static_cast<std::ptrdiff_t>(data_offset());
  496. }
  497. // TODO: fix the data_xend implementation and assign_temporary_impl
  498. template <class CT, class S, layout_type L, class FST>
  499. template <class It>
  500. inline It
  501. xdynamic_view<CT, S, L, FST>::data_xend_impl(It begin, layout_type l, size_type offset) const noexcept
  502. {
  503. return strided_data_end(*this, begin + std::ptrdiff_t(data_offset()), l, offset);
  504. }
  505. template <class CT, class S, layout_type L, class FST>
  506. inline void xdynamic_view<CT, S, L, FST>::assign_temporary_impl(temporary_type&& tmp)
  507. {
  508. std::copy(tmp.cbegin(), tmp.cend(), this->begin());
  509. }
  510. template <class CT, class S, layout_type L, class FST>
  511. template <class T, class... Args>
  512. inline auto
  513. xdynamic_view<CT, S, L, FST>::adjust_offset(offset_type offset, T idx, Args... args) const noexcept
  514. -> offset_type
  515. {
  516. constexpr size_type nb_args = sizeof...(Args) + 1;
  517. size_type dim = base_type::dimension();
  518. offset_type res = nb_args > dim ? adjust_offset(offset, args...)
  519. : adjust_offset_impl(offset, dim - nb_args, idx, args...);
  520. return res;
  521. }
  522. template <class CT, class S, layout_type L, class FST>
  523. inline auto xdynamic_view<CT, S, L, FST>::adjust_offset(offset_type offset) const noexcept -> offset_type
  524. {
  525. return offset;
  526. }
  527. template <class CT, class S, layout_type L, class FST>
  528. template <class T, class... Args>
  529. inline auto
  530. xdynamic_view<CT, S, L, FST>::adjust_offset_impl(offset_type offset, size_type idx_offset, T idx, Args... args)
  531. const noexcept -> offset_type
  532. {
  533. offset_type sl_offset = xtl::visit(
  534. [idx](const auto& sl)
  535. {
  536. using type = typename std::decay_t<decltype(sl)>::size_type;
  537. return sl(type(idx));
  538. },
  539. m_slices[idx_offset]
  540. );
  541. offset_type res = offset + sl_offset * m_adj_strides[idx_offset];
  542. return adjust_offset_impl(res, idx_offset + 1, args...);
  543. }
  544. template <class CT, class S, layout_type L, class FST>
  545. inline auto xdynamic_view<CT, S, L, FST>::adjust_offset_impl(offset_type offset, size_type) const noexcept
  546. -> offset_type
  547. {
  548. return offset;
  549. }
  550. template <class CT, class S, layout_type L, class FST>
  551. template <class It>
  552. inline auto
  553. xdynamic_view<CT, S, L, FST>::adjust_element_offset(offset_type offset, It first, It last) const noexcept
  554. -> offset_type
  555. {
  556. auto dst = std::distance(first, last);
  557. offset_type dim = static_cast<offset_type>(dimension());
  558. offset_type loop_offset = dst < dim ? dim - dst : offset_type(0);
  559. offset_type idx_offset = dim < dst ? dst - dim : offset_type(0);
  560. offset_type res = offset;
  561. for (offset_type i = loop_offset; i < dim; ++i, ++first)
  562. {
  563. offset_type j = static_cast<offset_type>(first[idx_offset]);
  564. offset_type sl_offset = xtl::visit(
  565. [j](const auto& sl)
  566. {
  567. return static_cast<offset_type>(sl(j));
  568. },
  569. m_slices[static_cast<std::size_t>(i)]
  570. );
  571. res += sl_offset * m_adj_strides[static_cast<std::size_t>(i)];
  572. }
  573. return res;
  574. }
  575. /*****************************************
  576. * xdynamic_view builders implementation *
  577. *****************************************/
  578. namespace detail
  579. {
  580. template <class V>
  581. struct adj_strides_policy
  582. {
  583. using slice_vector = V;
  584. using strides_type = dynamic_shape<std::ptrdiff_t>;
  585. slice_vector new_slices;
  586. strides_type new_adj_strides;
  587. protected:
  588. inline void resize(std::size_t size)
  589. {
  590. new_slices.resize(size);
  591. new_adj_strides.resize(size);
  592. }
  593. inline void set_fake_slice(std::size_t idx)
  594. {
  595. new_slices[idx] = xfake_slice<std::ptrdiff_t>();
  596. new_adj_strides[idx] = std::ptrdiff_t(0);
  597. }
  598. template <class ST, class S>
  599. bool fill_args(
  600. const xdynamic_slice_vector& slices,
  601. std::size_t sl_idx,
  602. std::size_t i,
  603. std::size_t old_shape,
  604. const ST& old_stride,
  605. S& shape,
  606. get_strides_t<S>& strides
  607. )
  608. {
  609. return fill_args_impl<xkeep_slice<std::ptrdiff_t>>(
  610. slices,
  611. sl_idx,
  612. i,
  613. old_shape,
  614. old_stride,
  615. shape,
  616. strides
  617. )
  618. || fill_args_impl<xdrop_slice<std::ptrdiff_t>>(
  619. slices,
  620. sl_idx,
  621. i,
  622. old_shape,
  623. old_stride,
  624. shape,
  625. strides
  626. );
  627. }
  628. template <class SL, class ST, class S>
  629. bool fill_args_impl(
  630. const xdynamic_slice_vector& slices,
  631. std::size_t sl_idx,
  632. std::size_t i,
  633. std::size_t old_shape,
  634. const ST& old_stride,
  635. S& shape,
  636. get_strides_t<S>& strides
  637. )
  638. {
  639. auto* sl = xtl::get_if<SL>(&slices[sl_idx]);
  640. if (sl != nullptr)
  641. {
  642. new_slices[i] = *sl;
  643. auto& ns = xtl::get<SL>(new_slices[i]);
  644. ns.normalize(old_shape);
  645. shape[i] = static_cast<std::size_t>(ns.size());
  646. strides[i] = std::ptrdiff_t(0);
  647. new_adj_strides[i] = static_cast<std::ptrdiff_t>(old_stride);
  648. }
  649. return sl != nullptr;
  650. }
  651. };
  652. }
  653. template <class E>
  654. inline auto dynamic_view(E&& e, const xdynamic_slice_vector& slices)
  655. {
  656. using view_type = xdynamic_view<xclosure_t<E>, dynamic_shape<std::size_t>>;
  657. using slice_vector = typename view_type::slice_vector_type;
  658. using policy = detail::adj_strides_policy<slice_vector>;
  659. detail::strided_view_args<policy> args;
  660. args.fill_args(
  661. e.shape(),
  662. detail::get_strides<XTENSOR_DEFAULT_TRAVERSAL>(e),
  663. detail::get_offset<XTENSOR_DEFAULT_TRAVERSAL>(e),
  664. e.layout(),
  665. slices
  666. );
  667. return view_type(
  668. std::forward<E>(e),
  669. std::move(args.new_shape),
  670. std::move(args.new_strides),
  671. args.new_offset,
  672. args.new_layout,
  673. std::move(args.new_slices),
  674. std::move(args.new_adj_strides)
  675. );
  676. }
  677. }
  678. #endif