9#ifndef XTENSOR_DYNAMIC_VIEW_HPP
10#define XTENSOR_DYNAMIC_VIEW_HPP
14#include <xtl/xsequence.hpp>
16#include "../core/xexpression.hpp"
17#include "../core/xiterable.hpp"
18#include "../core/xlayout.hpp"
19#include "../core/xsemantic.hpp"
20#include "../views/xstrided_view_base.hpp"
25 template <
class CT,
class S, layout_type L,
class FST>
28 template <
class CT,
class S, layout_type L,
class FST>
31 using xexpression_type = std::decay_t<CT>;
32 using undecay_expression = CT;
33 using reference = inner_reference_t<undecay_expression>;
34 using const_reference =
typename xexpression_type::const_reference;
35 using size_type =
typename xexpression_type::size_type;
36 using shape_type = std::decay_t<S>;
37 using undecay_shape = S;
38 using storage_getter = FST;
39 using inner_storage_type =
typename storage_getter::type;
44 template <
class CT,
class S, layout_type L,
class FST>
47 using inner_shape_type = S;
48 using inner_strides_type = inner_shape_type;
49 using inner_backstrides_type = inner_shape_type;
51#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ == 8
69 template <
class Tag,
class CT,
class S, layout_type L,
class FST>
72 template <
class CT,
class S, layout_type L,
class FST>
78 template <
class CT,
class S, layout_type L,
class FST>
83 template <
class CT,
class S, layout_type L,
class FST>
97 template <
class CT,
class S, layout_type L = layout_type::dynamic,
class FST = detail::flat_storage_getter<CT, XTENSOR_DEFAULT_TRAVERSAL>>
98 class xdynamic_view :
public xview_semantic<xdynamic_view<CT, S, L, FST>>,
99 public xiterable<xdynamic_view<CT, S, L, FST>>,
100 public extension::xdynamic_view_base_t<CT, S, L, FST>,
105 using self_type = xdynamic_view<CT, S, L, FST>;
107 using semantic_base = xview_semantic<self_type>;
108 using extension_base = extension::xdynamic_view_base_t<CT, S, L, FST>;
109 using expression_tag =
typename extension_base::expression_tag;
111 using xexpression_type =
typename base_type::xexpression_type;
112 using base_type::is_const;
114 using value_type =
typename base_type::value_type;
115 using reference =
typename base_type::reference;
116 using const_reference =
typename base_type::const_reference;
117 using pointer =
typename base_type::pointer;
118 using const_pointer =
typename base_type::const_pointer;
119 using size_type =
typename base_type::size_type;
120 using difference_type =
typename base_type::difference_type;
122 using inner_storage_type =
typename base_type::inner_storage_type;
123 using storage_type =
typename base_type::storage_type;
126 using inner_shape_type =
typename iterable_base::inner_shape_type;
127 using inner_strides_type =
typename base_type::inner_strides_type;
128 using inner_backstrides_type =
typename base_type::inner_backstrides_type;
130 using shape_type =
typename base_type::shape_type;
131 using strides_type =
typename base_type::strides_type;
132 using backstrides_type =
typename base_type::backstrides_type;
134 using stepper =
typename iterable_base::stepper;
135 using const_stepper =
typename iterable_base::const_stepper;
137 using base_type::contiguous_layout;
138 using base_type::static_layout;
141 using base_index_type = xindex_type_t<shape_type>;
143 using simd_value_type =
typename base_type::simd_value_type;
144 using bool_load_type =
typename base_type::bool_load_type;
146 using strides_vt =
typename strides_type::value_type;
148 using slice_vector_type = std::vector<slice_type>;
150 template <
class CTA,
class SA>
154 get_strides_t<S>&& strides,
157 slice_vector_type&& slices,
158 get_strides_t<S>&& adj_strides
165 disable_xexpression<E, self_type>& operator=(
const E& e);
168 using base_type::is_contiguous;
176 const inner_strides_type& strides()
const noexcept =
delete;
178 reference operator()();
179 const_reference operator()()
const;
181 template <
class... Args>
182 reference operator()(Args... args);
184 template <
class... Args>
185 const_reference operator()(Args... args)
const;
187 template <
class... Args>
188 reference unchecked(Args... args);
190 template <
class... Args>
191 const_reference unchecked(Args... args)
const;
193 reference flat(size_type index);
194 const_reference flat(size_type index)
const;
196 using base_type::operator[];
201 using base_type::periodic;
204 reference element(It first, It last);
207 const_reference element(It first, It last)
const;
209 size_type data_offset()
const noexcept;
214 value_type* data()
noexcept =
delete;
215 const value_type* data()
const noexcept =
delete;
222 bool has_linear_assign(
const O& str)
const noexcept;
225 void fill(
const T& value);
228 stepper stepper_begin(
const ST&
shape);
233 const_stepper stepper_begin(
const ST&
shape)
const;
237 using container_iterator = std::
238 conditional_t<is_const, typename storage_type::const_iterator, typename storage_type::iterator>;
239 using const_container_iterator =
typename storage_type::const_iterator;
242 using rebind_t = xdynamic_view<E, S, L, typename FST::template rebind_t<E>>;
245 rebind_t<E> build_view(E&& e)
const;
249 using offset_type =
typename base_type::offset_type;
251 slice_vector_type m_slices;
252 inner_strides_type m_adj_strides;
254 container_iterator data_xbegin()
noexcept;
255 const_container_iterator data_xbegin()
const noexcept;
256 container_iterator data_xend(
layout_type l, size_type offset)
noexcept;
257 const_container_iterator data_xend(
layout_type l, size_type offset)
const noexcept;
260 It data_xbegin_impl(It begin)
const noexcept;
263 It data_xend_impl(It end,
layout_type l, size_type offset)
const noexcept;
265 void assign_temporary_impl(temporary_type&& tmp);
267 template <
class T,
class... Args>
268 offset_type adjust_offset(offset_type offset, T idx, Args... args)
const noexcept;
269 offset_type adjust_offset(offset_type offset)
const noexcept;
271 template <
class T,
class... Args>
273 adjust_offset_impl(offset_type offset, size_type idx_offset, T idx, Args... args)
const noexcept;
274 offset_type adjust_offset_impl(offset_type offset, size_type idx_offset)
const noexcept;
277 offset_type adjust_element_offset(offset_type offset, It first, It last)
const noexcept;
280 friend class xstepper;
281 friend class xview_semantic<self_type>;
291 using xdynamic_slice = std::variant<
315 using xdynamic_slice_vector = std::vector<xdynamic_slice<std::ptrdiff_t>>;
318 auto dynamic_view(E&& e,
const xdynamic_slice_vector& slices);
327 class xfake_slice :
public xslice<xfake_slice<T>>
332 using self_type = xfake_slice<T>;
334 xfake_slice() =
default;
336 size_type operator()(size_type )
const noexcept
341 size_type size() const noexcept
346 size_type step_size() const noexcept
351 size_type step_size(std::size_t , std::size_t = 1) const noexcept
356 size_type revert_index(std::size_t i)
const noexcept
361 bool contains(size_type )
const noexcept
366 bool operator==(
const self_type& )
const noexcept
371 bool operator!=(
const self_type& )
const noexcept
382 template <
class CT,
class S, layout_type L,
class FST>
383 template <
class CTA,
class SA>
384 inline xdynamic_view<CT, S, L, FST>::xdynamic_view(
390 slice_vector_type&& slices,
391 get_strides_t<S>&& adj_strides
393 : base_type(std::forward<CTA>(e), std::forward<SA>(shape), std::move(
strides), offset, layout)
394 , m_slices(std::move(slices))
395 , m_adj_strides(std::move(adj_strides))
399 template <
class CT,
class S, layout_type L,
class FST>
401 inline auto xdynamic_view<CT, S, L, FST>::operator=(
const xexpression<E>& e) -> self_type&
403 return semantic_base::operator=(e);
406 template <
class CT,
class S, layout_type L,
class FST>
408 inline auto xdynamic_view<CT, S, L, FST>::operator=(
const E& e) -> disable_xexpression<E, self_type>&
410 std::fill(this->begin(), this->end(), e);
414 template <
class CT,
class S, layout_type L,
class FST>
415 inline auto xdynamic_view<CT, S, L, FST>::operator()() -> reference
417 return base_type::storage()[data_offset()];
420 template <
class CT,
class S, layout_type L,
class FST>
421 inline auto xdynamic_view<CT, S, L, FST>::operator()() const -> const_reference
423 return base_type::storage()[data_offset()];
426 template <
class CT,
class S, layout_type L,
class FST>
427 template <
class... Args>
428 inline auto xdynamic_view<CT, S, L, FST>::operator()(Args... args) -> reference
430 XTENSOR_TRY(check_index(base_type::shape(), args...));
431 XTENSOR_CHECK_DIMENSION(base_type::shape(), args...);
432 offset_type offset = base_type::compute_index(args...);
433 offset = adjust_offset(offset, args...);
434 return base_type::storage()[
static_cast<size_type
>(offset)];
437 template <
class CT,
class S, layout_type L,
class FST>
438 template <
class... Args>
439 inline auto xdynamic_view<CT, S, L, FST>::operator()(Args... args)
const -> const_reference
441 XTENSOR_TRY(check_index(base_type::shape(), args...));
442 XTENSOR_CHECK_DIMENSION(base_type::shape(), args...);
443 offset_type offset = base_type::compute_index(args...);
444 offset = adjust_offset(offset, args...);
445 return base_type::storage()[
static_cast<size_type
>(offset)];
448 template <
class CT,
class S, layout_type L,
class FST>
450 inline bool xdynamic_view<CT, S, L, FST>::has_linear_assign(
const O&)
const noexcept
455 template <
class CT,
class S, layout_type L,
class FST>
456 template <
class... Args>
457 inline auto xdynamic_view<CT, S, L, FST>::unchecked(Args... args) -> reference
459 offset_type offset = base_type::compute_unchecked_index(args...);
460 offset = adjust_offset(args...);
461 return base_type::storage()[
static_cast<size_type
>(offset)];
464 template <
class CT,
class S, layout_type L,
class FST>
465 template <
class... Args>
466 inline auto xdynamic_view<CT, S, L, FST>::unchecked(Args... args)
const -> const_reference
468 offset_type offset = base_type::compute_unchecked_index(args...);
469 offset = adjust_offset(args...);
470 return base_type::storage()[
static_cast<size_type
>(offset)];
473 template <
class CT,
class S, layout_type L,
class FST>
474 inline auto xdynamic_view<CT, S, L, FST>::flat(size_type i) -> reference
476 return base_type::storage()[data_offset() + i];
479 template <
class CT,
class S, layout_type L,
class FST>
480 inline auto xdynamic_view<CT, S, L, FST>::flat(size_type i)
const -> const_reference
482 return base_type::storage()[data_offset() + i];
485 template <
class CT,
class S, layout_type L,
class FST>
487 inline auto xdynamic_view<CT, S, L, FST>::element(It first, It last) -> reference
489 XTENSOR_TRY(check_element_index(base_type::shape(), first, last));
490 offset_type offset = base_type::compute_element_index(first, last);
491 offset = adjust_element_offset(offset, first, last);
492 return base_type::storage()[
static_cast<size_type
>(offset)];
495 template <
class CT,
class S, layout_type L,
class FST>
497 inline auto xdynamic_view<CT, S, L, FST>::element(It first, It last)
const -> const_reference
499 XTENSOR_TRY(check_element_index(base_type::shape(), first, last));
500 offset_type offset = base_type::compute_element_index(first, last);
501 offset = adjust_element_offset(offset, first, last);
502 return base_type::storage()[
static_cast<size_type
>(offset)];
505 template <
class CT,
class S, layout_type L,
class FST>
506 inline auto xdynamic_view<CT, S, L, FST>::data_offset() const noexcept -> size_type
508 size_type offset = base_type::data_offset();
509 size_type sl_offset = std::visit(
512 return sl(size_type(0));
516 return offset + sl_offset * m_adj_strides[0];
519 template <
class CT,
class S, layout_type L,
class FST>
521 inline void xdynamic_view<CT, S, L, FST>::fill(
const T& value)
523 return std::fill(this->linear_begin(), this->linear_end(), value);
526 template <
class CT,
class S, layout_type L,
class FST>
528 inline auto xdynamic_view<CT, S, L, FST>::stepper_begin(
const ST& shape) -> stepper
530 size_type offset = shape.size() - dimension();
531 return stepper(
this, offset);
534 template <
class CT,
class S, layout_type L,
class FST>
536 inline auto xdynamic_view<CT, S, L, FST>::stepper_end(
const ST& shape,
layout_type ) -> stepper
538 size_type offset = shape.size() - dimension();
539 return stepper(
this, offset,
true);
542 template <
class CT,
class S, layout_type L,
class FST>
544 inline auto xdynamic_view<CT, S, L, FST>::stepper_begin(
const ST& shape)
const -> const_stepper
546 size_type offset = shape.size() - dimension();
547 return const_stepper(
this, offset);
550 template <
class CT,
class S, layout_type L,
class FST>
552 inline auto xdynamic_view<CT, S, L, FST>::stepper_end(
const ST& shape,
layout_type )
const
555 size_type offset = shape.size() - dimension();
556 return const_stepper(
this, offset,
true);
559 template <
class CT,
class S, layout_type L,
class FST>
561 inline auto xdynamic_view<CT, S, L, FST>::build_view(E&& e)
const -> rebind_t<E>
563 inner_shape_type sh(this->shape());
564 inner_strides_type str(base_type::strides());
565 slice_vector_type svt(m_slices);
566 inner_strides_type adj_str(m_adj_strides);
571 base_type::data_offset(),
578 template <
class CT,
class S, layout_type L,
class FST>
579 inline auto xdynamic_view<CT, S, L, FST>::data_xbegin() noexcept -> container_iterator
581 return data_xbegin_impl(this->storage().begin());
584 template <
class CT,
class S, layout_type L,
class FST>
585 inline auto xdynamic_view<CT, S, L, FST>::data_xbegin() const noexcept -> const_container_iterator
587 return data_xbegin_impl(this->storage().cbegin());
590 template <
class CT,
class S, layout_type L,
class FST>
591 inline auto xdynamic_view<CT, S, L, FST>::data_xend(
layout_type l, size_type offset)
noexcept
592 -> container_iterator
594 return data_xend_impl(this->storage().begin(), l, offset);
597 template <
class CT,
class S, layout_type L,
class FST>
598 inline auto xdynamic_view<CT, S, L, FST>::data_xend(
layout_type l, size_type offset)
const noexcept
599 -> const_container_iterator
601 return data_xend_impl(this->storage().cbegin(), l, offset);
604 template <
class CT,
class S, layout_type L,
class FST>
606 inline It xdynamic_view<CT, S, L, FST>::data_xbegin_impl(It begin)
const noexcept
608 return begin +
static_cast<std::ptrdiff_t
>(data_offset());
613 template <
class CT,
class S, layout_type L,
class FST>
616 xdynamic_view<CT, S, L, FST>::data_xend_impl(It begin,
layout_type l, size_type offset)
const noexcept
618 return strided_data_end(*
this, begin + std::ptrdiff_t(data_offset()), l, offset);
621 template <
class CT,
class S, layout_type L,
class FST>
622 inline void xdynamic_view<CT, S, L, FST>::assign_temporary_impl(
temporary_type&& tmp)
624 std::copy(tmp.cbegin(), tmp.cend(), this->begin());
627 template <
class CT,
class S, layout_type L,
class FST>
628 template <
class T,
class... Args>
630 xdynamic_view<CT, S, L, FST>::adjust_offset(offset_type offset, T idx, Args... args)
const noexcept
633 constexpr size_type nb_args =
sizeof...(Args) + 1;
634 size_type dim = base_type::dimension();
635 offset_type res = nb_args > dim ? adjust_offset(offset, args...)
636 : adjust_offset_impl(offset, dim - nb_args, idx, args...);
640 template <
class CT,
class S, layout_type L,
class FST>
641 inline auto xdynamic_view<CT, S, L, FST>::adjust_offset(offset_type offset)
const noexcept -> offset_type
646 template <
class CT,
class S, layout_type L,
class FST>
647 template <
class T,
class... Args>
649 xdynamic_view<CT, S, L, FST>::adjust_offset_impl(offset_type offset, size_type idx_offset, T idx, Args... args)
650 const noexcept -> offset_type
652 offset_type sl_offset = std::visit(
653 [idx](
const auto& sl)
655 using type =
typename std::decay_t<
decltype(sl)>::size_type;
656 return sl(type(idx));
660 offset_type res = offset + sl_offset * m_adj_strides[idx_offset];
661 return adjust_offset_impl(res, idx_offset + 1, args...);
664 template <
class CT,
class S, layout_type L,
class FST>
665 inline auto xdynamic_view<CT, S, L, FST>::adjust_offset_impl(offset_type offset, size_type)
const noexcept
671 template <
class CT,
class S, layout_type L,
class FST>
674 xdynamic_view<CT, S, L, FST>::adjust_element_offset(offset_type offset, It first, It last)
const noexcept
677 auto dst = std::distance(first, last);
678 offset_type dim =
static_cast<offset_type
>(dimension());
679 offset_type loop_offset = dst < dim ? dim - dst : offset_type(0);
680 offset_type idx_offset = dim < dst ? dst - dim : offset_type(0);
681 offset_type res = offset;
682 for (offset_type i = loop_offset; i < dim; ++i, ++first)
684 offset_type j =
static_cast<offset_type
>(first[idx_offset]);
685 offset_type sl_offset = std::visit(
688 return static_cast<offset_type
>(sl(j));
690 m_slices[
static_cast<std::size_t
>(i)]
692 res += sl_offset * m_adj_strides[
static_cast<std::size_t
>(i)];
704 struct adj_strides_policy
706 using slice_vector = V;
707 using strides_type = dynamic_shape<std::ptrdiff_t>;
709 slice_vector new_slices;
710 strides_type new_adj_strides;
714 inline void resize(std::size_t size)
716 new_slices.resize(size);
717 new_adj_strides.resize(size);
720 inline void set_fake_slice(std::size_t idx)
722 new_slices[idx] = xfake_slice<std::ptrdiff_t>();
723 new_adj_strides[idx] = std::ptrdiff_t(0);
726 template <
class ST,
class S>
728 const xdynamic_slice_vector& slices,
731 std::size_t old_shape,
732 const ST& old_stride,
737 return fill_args_impl<xkeep_slice<std::ptrdiff_t>>(
746 || fill_args_impl<xdrop_slice<std::ptrdiff_t>>(
757 template <
class SL,
class ST,
class S>
759 const xdynamic_slice_vector& slices,
762 std::size_t old_shape,
763 const ST& old_stride,
768 auto* sl = std::get_if<SL>(&slices[sl_idx]);
772 auto& ns = std::get<SL>(new_slices[i]);
773 ns.normalize(old_shape);
774 shape[i] =
static_cast<std::size_t
>(ns.size());
775 strides[i] = std::ptrdiff_t(0);
776 new_adj_strides[i] =
static_cast<std::ptrdiff_t
>(old_stride);
778 return sl !=
nullptr;
784 inline auto dynamic_view(E&& e,
const xdynamic_slice_vector& slices)
787 using slice_vector =
typename view_type::slice_vector_type;
788 using policy = detail::adj_strides_policy<slice_vector>;
789 detail::strided_view_args<policy> args;
792 detail::get_strides<XTENSOR_DEFAULT_TRAVERSAL>(e),
793 detail::get_offset<XTENSOR_DEFAULT_TRAVERSAL>(e),
799 std::move(args.new_shape),
800 std::move(args.new_strides),
803 std::move(args.new_slices),
804 std::move(args.new_adj_strides)
Base class for implementation of common expression access methods.
Base class for implementation of common expression constant access methods.
const_reference front() const
size_type size() const noexcept
size_type dimension() const noexcept
bool in_bounds(Args... args) const
const_reference back() const
const inner_shape_type & shape() const noexcept
Returns the shape of the xtrided_view_base.
layout_type layout() const noexcept
Returns the layout of the xtrided_view_base.
Base class for xexpressions.
Base class for multidimensional iterable expressions.
layout_type layout() const noexcept
xstrided_view_base(CTA &&e, SA &&shape, strides_type &&strides, size_type offset, layout_type layout) noexcept
Constructs an xstrided_view_base.
bool broadcast_shape(O &shape, bool reuse_cache=false) const
const inner_shape_type & shape() const noexcept
storage_type & storage() noexcept
xexpression_type & expression() noexcept
auto strides(const E &e, stride_type type=stride_type::normal) noexcept
Get strides of an object.
standard mathematical functions for xexpressions
xarray_container< uvector< T, A >, L, xt::svector< typename uvector< T, A >::size_type, 4, SA, true > > xarray
Alias template on xarray_container with default parameters for data container type and shape / stride...