9#ifndef XTENSOR_DYNAMIC_VIEW_HPP
10#define XTENSOR_DYNAMIC_VIEW_HPP
12#include <xtl/xsequence.hpp>
13#include <xtl/xvariant.hpp>
15#include "xexpression.hpp"
16#include "xiterable.hpp"
18#include "xsemantic.hpp"
19#include "xstrided_view_base.hpp"
24 template <
class CT,
class S, layout_type L,
class FST>
27 template <
class CT,
class S, layout_type L,
class FST>
30 using xexpression_type = std::decay_t<CT>;
33 using const_reference =
typename xexpression_type::const_reference;
34 using size_type =
typename xexpression_type::size_type;
35 using shape_type = std::decay_t<S>;
38 using inner_storage_type =
typename storage_getter::type;
43 template <
class CT,
class S, layout_type L,
class FST>
50#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ == 8
68 template <
class Tag,
class CT,
class S, layout_type L,
class FST>
71 template <
class CT,
class S, layout_type L,
class FST>
77 template <
class CT,
class S, layout_type L,
class FST>
82 template <
class CT,
class S, layout_type L,
class FST>
96 template <
class CT,
class S, layout_type L = layout_type::dynamic,
class FST = detail::flat_storage_getter<CT, XTENSOR_DEFAULT_TRAVERSAL>>
98 public xiterable<xdynamic_view<CT, S, L, FST>>,
99 public extension::xdynamic_view_base_t<CT, S, L, FST>,
107 using extension_base = extension::xdynamic_view_base_t<CT, S, L, FST>;
108 using expression_tag =
typename extension_base::expression_tag;
110 using xexpression_type =
typename base_type::xexpression_type;
111 using base_type::is_const;
113 using value_type =
typename base_type::value_type;
114 using reference =
typename base_type::reference;
115 using const_reference =
typename base_type::const_reference;
116 using pointer =
typename base_type::pointer;
117 using const_pointer =
typename base_type::const_pointer;
118 using size_type =
typename base_type::size_type;
119 using difference_type =
typename base_type::difference_type;
121 using inner_storage_type =
typename base_type::inner_storage_type;
122 using storage_type =
typename base_type::storage_type;
125 using inner_shape_type =
typename iterable_base::inner_shape_type;
126 using inner_strides_type =
typename base_type::inner_strides_type;
129 using shape_type =
typename base_type::shape_type;
133 using stepper =
typename iterable_base::stepper;
134 using const_stepper =
typename iterable_base::const_stepper;
136 using base_type::contiguous_layout;
137 using base_type::static_layout;
142 using simd_value_type =
typename base_type::simd_value_type;
143 using bool_load_type =
typename base_type::bool_load_type;
145 using strides_vt =
typename strides_type::value_type;
147 using slice_vector_type = std::vector<slice_type>;
149 template <
class CTA,
class SA>
156 slice_vector_type&& slices,
167 using base_type::is_contiguous;
175 const inner_strides_type& strides()
const noexcept =
delete;
177 reference operator()();
178 const_reference operator()()
const;
180 template <
class...
Args>
183 template <
class...
Args>
184 const_reference operator()(
Args...
args)
const;
186 template <
class...
Args>
189 template <
class...
Args>
190 const_reference unchecked(
Args...
args)
const;
192 reference flat(size_type index);
193 const_reference flat(size_type index)
const;
195 using base_type::operator[];
200 using base_type::periodic;
208 size_type data_offset()
const noexcept;
213 value_type* data()
noexcept =
delete;
214 const value_type* data()
const noexcept =
delete;
221 bool has_linear_assign(
const O&
str)
const noexcept;
224 void fill(
const T& value);
227 stepper stepper_begin(
const ST&
shape);
232 const_stepper stepper_begin(
const ST&
shape)
const;
236 using container_iterator = std::
237 conditional_t<is_const, typename storage_type::const_iterator, typename storage_type::iterator>;
238 using const_container_iterator =
typename storage_type::const_iterator;
248 using offset_type =
typename base_type::offset_type;
250 slice_vector_type m_slices;
251 inner_strides_type m_adj_strides;
253 container_iterator data_xbegin()
noexcept;
254 const_container_iterator data_xbegin()
const noexcept;
259 It data_xbegin_impl(
It begin)
const noexcept;
264 void assign_temporary_impl(temporary_type&&
tmp);
266 template <
class T,
class...
Args>
267 offset_type adjust_offset(offset_type
offset, T idx,
Args...
args)
const noexcept;
268 offset_type adjust_offset(offset_type
offset)
const noexcept;
270 template <
class T,
class...
Args>
273 offset_type adjust_offset_impl(offset_type
offset, size_type
idx_offset)
const noexcept;
290 using xdynamic_slice = xtl::variant<
314 using xdynamic_slice_vector = std::vector<xdynamic_slice<std::ptrdiff_t>>;
317 auto dynamic_view(E&&
e,
const xdynamic_slice_vector& slices);
326 class xfake_slice :
public xslice<xfake_slice<T>>
333 xfake_slice() =
default;
335 size_type operator()(size_type )
const noexcept
340 size_type size() const noexcept
345 size_type step_size() const noexcept
350 size_type step_size(std::size_t , std::size_t = 1) const noexcept
355 size_type revert_index(std::size_t i)
const noexcept
360 bool contains(size_type )
const noexcept
365 bool operator==(
const self_type& )
const noexcept
370 bool operator!=(
const self_type& )
const noexcept
381 template <
class CT,
class S, layout_type L,
class FST>
382 template <
class CTA,
class SA>
383 inline xdynamic_view<CT, S, L, FST>::xdynamic_view(
389 slice_vector_type&& slices,
390 get_strides_t<S>&& adj_strides
392 : base_type(std::forward<CTA>(e), std::forward<SA>(shape), std::move(
strides), offset, layout)
393 , m_slices(std::move(slices))
394 , m_adj_strides(std::move(adj_strides))
398 template <
class CT,
class S, layout_type L,
class FST>
400 inline auto xdynamic_view<CT, S, L, FST>::operator=(
const xexpression<E>& e) -> self_type&
402 return semantic_base::operator=(e);
405 template <
class CT,
class S, layout_type L,
class FST>
407 inline auto xdynamic_view<CT, S, L, FST>::operator=(
const E& e) -> disable_xexpression<E, self_type>&
409 std::fill(this->begin(), this->end(), e);
413 template <
class CT,
class S, layout_type L,
class FST>
414 inline auto xdynamic_view<CT, S, L, FST>::operator()() -> reference
416 return base_type::storage()[data_offset()];
419 template <
class CT,
class S, layout_type L,
class FST>
420 inline auto xdynamic_view<CT, S, L, FST>::operator()() const -> const_reference
422 return base_type::storage()[data_offset()];
425 template <
class CT,
class S, layout_type L,
class FST>
426 template <
class... Args>
427 inline auto xdynamic_view<CT, S, L, FST>::operator()(Args... args) -> reference
429 XTENSOR_TRY(check_index(base_type::shape(), args...));
430 XTENSOR_CHECK_DIMENSION(base_type::shape(), args...);
431 offset_type offset = base_type::compute_index(args...);
432 offset = adjust_offset(offset, args...);
433 return base_type::storage()[
static_cast<size_type
>(offset)];
436 template <
class CT,
class S, layout_type L,
class FST>
437 template <
class... Args>
438 inline auto xdynamic_view<CT, S, L, FST>::operator()(Args... args)
const -> const_reference
440 XTENSOR_TRY(check_index(base_type::shape(), args...));
441 XTENSOR_CHECK_DIMENSION(base_type::shape(), args...);
442 offset_type offset = base_type::compute_index(args...);
443 offset = adjust_offset(offset, args...);
444 return base_type::storage()[
static_cast<size_type
>(offset)];
447 template <
class CT,
class S, layout_type L,
class FST>
449 inline bool xdynamic_view<CT, S, L, FST>::has_linear_assign(
const O&)
const noexcept
454 template <
class CT,
class S, layout_type L,
class FST>
455 template <
class... Args>
456 inline auto xdynamic_view<CT, S, L, FST>::unchecked(Args... args) -> reference
458 offset_type offset = base_type::compute_unchecked_index(args...);
459 offset = adjust_offset(args...);
460 return base_type::storage()[
static_cast<size_type
>(offset)];
463 template <
class CT,
class S, layout_type L,
class FST>
464 template <
class... Args>
465 inline auto xdynamic_view<CT, S, L, FST>::unchecked(Args... args)
const -> const_reference
467 offset_type offset = base_type::compute_unchecked_index(args...);
468 offset = adjust_offset(args...);
469 return base_type::storage()[
static_cast<size_type
>(offset)];
472 template <
class CT,
class S, layout_type L,
class FST>
473 inline auto xdynamic_view<CT, S, L, FST>::flat(size_type i) -> reference
475 return base_type::storage()[data_offset() + i];
478 template <
class CT,
class S, layout_type L,
class FST>
479 inline auto xdynamic_view<CT, S, L, FST>::flat(size_type i)
const -> const_reference
481 return base_type::storage()[data_offset() + i];
484 template <
class CT,
class S, layout_type L,
class FST>
486 inline auto xdynamic_view<CT, S, L, FST>::element(It first, It last) -> reference
488 XTENSOR_TRY(check_element_index(base_type::shape(), first, last));
489 offset_type offset = base_type::compute_element_index(first, last);
490 offset = adjust_element_offset(offset, first, last);
491 return base_type::storage()[
static_cast<size_type
>(offset)];
494 template <
class CT,
class S, layout_type L,
class FST>
496 inline auto xdynamic_view<CT, S, L, FST>::element(It first, It last)
const -> const_reference
498 XTENSOR_TRY(check_element_index(base_type::shape(), first, last));
499 offset_type offset = base_type::compute_element_index(first, last);
500 offset = adjust_element_offset(offset, first, last);
501 return base_type::storage()[
static_cast<size_type
>(offset)];
504 template <
class CT,
class S, layout_type L,
class FST>
505 inline auto xdynamic_view<CT, S, L, FST>::data_offset() const noexcept -> size_type
507 size_type offset = base_type::data_offset();
508 size_type sl_offset = xtl::visit(
511 return sl(size_type(0));
515 return offset + sl_offset * m_adj_strides[0];
518 template <
class CT,
class S, layout_type L,
class FST>
520 inline void xdynamic_view<CT, S, L, FST>::fill(
const T& value)
522 return std::fill(this->linear_begin(), this->linear_end(), value);
525 template <
class CT,
class S, layout_type L,
class FST>
527 inline auto xdynamic_view<CT, S, L, FST>::stepper_begin(
const ST& shape) -> stepper
529 size_type offset = shape.size() - dimension();
530 return stepper(
this, offset);
533 template <
class CT,
class S, layout_type L,
class FST>
535 inline auto xdynamic_view<CT, S, L, FST>::stepper_end(
const ST& shape,
layout_type ) -> stepper
537 size_type offset = shape.size() - dimension();
538 return stepper(
this, offset,
true);
541 template <
class CT,
class S, layout_type L,
class FST>
543 inline auto xdynamic_view<CT, S, L, FST>::stepper_begin(
const ST& shape)
const -> const_stepper
545 size_type offset = shape.size() - dimension();
546 return const_stepper(
this, offset);
549 template <
class CT,
class S, layout_type L,
class FST>
551 inline auto xdynamic_view<CT, S, L, FST>::stepper_end(
const ST& shape,
layout_type )
const
554 size_type offset = shape.size() - dimension();
555 return const_stepper(
this, offset,
true);
558 template <
class CT,
class S, layout_type L,
class FST>
560 inline auto xdynamic_view<CT, S, L, FST>::build_view(E&& e)
const -> rebind_t<E>
562 inner_shape_type sh(this->shape());
563 inner_strides_type str(base_type::strides());
564 slice_vector_type svt(m_slices);
565 inner_strides_type adj_str(m_adj_strides);
570 base_type::data_offset(),
577 template <
class CT,
class S, layout_type L,
class FST>
578 inline auto xdynamic_view<CT, S, L, FST>::data_xbegin() noexcept -> container_iterator
580 return data_xbegin_impl(this->storage().begin());
583 template <
class CT,
class S, layout_type L,
class FST>
584 inline auto xdynamic_view<CT, S, L, FST>::data_xbegin() const noexcept -> const_container_iterator
586 return data_xbegin_impl(this->storage().cbegin());
589 template <
class CT,
class S, layout_type L,
class FST>
590 inline auto xdynamic_view<CT, S, L, FST>::data_xend(
layout_type l, size_type offset)
noexcept
591 -> container_iterator
593 return data_xend_impl(this->storage().begin(), l, offset);
596 template <
class CT,
class S, layout_type L,
class FST>
597 inline auto xdynamic_view<CT, S, L, FST>::data_xend(
layout_type l, size_type offset)
const noexcept
598 -> const_container_iterator
600 return data_xend_impl(this->storage().cbegin(), l, offset);
603 template <
class CT,
class S, layout_type L,
class FST>
605 inline It xdynamic_view<CT, S, L, FST>::data_xbegin_impl(It begin)
const noexcept
607 return begin +
static_cast<std::ptrdiff_t
>(data_offset());
612 template <
class CT,
class S, layout_type L,
class FST>
615 xdynamic_view<CT, S, L, FST>::data_xend_impl(It begin,
layout_type l, size_type offset)
const noexcept
617 return strided_data_end(*
this, begin + std::ptrdiff_t(data_offset()), l, offset);
620 template <
class CT,
class S, layout_type L,
class FST>
621 inline void xdynamic_view<CT, S, L, FST>::assign_temporary_impl(temporary_type&& tmp)
623 std::copy(tmp.cbegin(), tmp.cend(), this->begin());
626 template <
class CT,
class S, layout_type L,
class FST>
627 template <
class T,
class... Args>
629 xdynamic_view<CT, S, L, FST>::adjust_offset(offset_type offset, T idx, Args... args)
const noexcept
632 constexpr size_type nb_args =
sizeof...(Args) + 1;
633 size_type dim = base_type::dimension();
634 offset_type res = nb_args > dim ? adjust_offset(offset, args...)
635 : adjust_offset_impl(offset, dim - nb_args, idx, args...);
639 template <
class CT,
class S, layout_type L,
class FST>
640 inline auto xdynamic_view<CT, S, L, FST>::adjust_offset(offset_type offset)
const noexcept -> offset_type
645 template <
class CT,
class S, layout_type L,
class FST>
646 template <
class T,
class... Args>
648 xdynamic_view<CT, S, L, FST>::adjust_offset_impl(offset_type offset, size_type idx_offset, T idx, Args... args)
649 const noexcept -> offset_type
651 offset_type sl_offset = xtl::visit(
652 [idx](
const auto& sl)
654 using type =
typename std::decay_t<
decltype(sl)>::size_type;
655 return sl(type(idx));
659 offset_type res = offset + sl_offset * m_adj_strides[idx_offset];
660 return adjust_offset_impl(res, idx_offset + 1, args...);
663 template <
class CT,
class S, layout_type L,
class FST>
664 inline auto xdynamic_view<CT, S, L, FST>::adjust_offset_impl(offset_type offset, size_type)
const noexcept
670 template <
class CT,
class S, layout_type L,
class FST>
673 xdynamic_view<CT, S, L, FST>::adjust_element_offset(offset_type offset, It first, It last)
const noexcept
676 auto dst = std::distance(first, last);
677 offset_type dim =
static_cast<offset_type
>(dimension());
678 offset_type loop_offset = dst < dim ? dim - dst : offset_type(0);
679 offset_type idx_offset = dim < dst ? dst - dim : offset_type(0);
680 offset_type res = offset;
681 for (offset_type i = loop_offset; i < dim; ++i, ++first)
683 offset_type j =
static_cast<offset_type
>(first[idx_offset]);
684 offset_type sl_offset = xtl::visit(
687 return static_cast<offset_type
>(sl(j));
689 m_slices[
static_cast<std::size_t
>(i)]
691 res += sl_offset * m_adj_strides[
static_cast<std::size_t
>(i)];
703 struct adj_strides_policy
705 using slice_vector = V;
706 using strides_type = dynamic_shape<std::ptrdiff_t>;
708 slice_vector new_slices;
709 strides_type new_adj_strides;
713 inline void resize(std::size_t size)
715 new_slices.resize(size);
716 new_adj_strides.resize(size);
719 inline void set_fake_slice(std::size_t idx)
721 new_slices[idx] = xfake_slice<std::ptrdiff_t>();
722 new_adj_strides[idx] = std::ptrdiff_t(0);
725 template <
class ST,
class S>
727 const xdynamic_slice_vector& slices,
730 std::size_t old_shape,
731 const ST& old_stride,
736 return fill_args_impl<xkeep_slice<std::ptrdiff_t>>(
745 || fill_args_impl<xdrop_slice<std::ptrdiff_t>>(
756 template <
class SL,
class ST,
class S>
758 const xdynamic_slice_vector& slices,
761 std::size_t old_shape,
762 const ST& old_stride,
767 auto* sl = xtl::get_if<SL>(&slices[sl_idx]);
771 auto& ns = xtl::get<SL>(new_slices[i]);
772 ns.normalize(old_shape);
773 shape[i] =
static_cast<std::size_t
>(ns.size());
774 strides[i] = std::ptrdiff_t(0);
775 new_adj_strides[i] =
static_cast<std::ptrdiff_t
>(old_stride);
777 return sl !=
nullptr;
783 inline auto dynamic_view(E&& e,
const xdynamic_slice_vector& slices)
785 using view_type = xdynamic_view<xclosure_t<E>, dynamic_shape<std::size_t>>;
786 using slice_vector =
typename view_type::slice_vector_type;
787 using policy = detail::adj_strides_policy<slice_vector>;
788 detail::strided_view_args<policy> args;
791 detail::get_strides<XTENSOR_DEFAULT_TRAVERSAL>(e),
792 detail::get_offset<XTENSOR_DEFAULT_TRAVERSAL>(e),
798 std::move(args.new_shape),
799 std::move(args.new_strides),
802 std::move(args.new_slices),
803 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
Returns a constant reference to first the element of the expression.
size_type size() const noexcept
Returns the size of the expression.
size_type dimension() const noexcept
Returns the number of dimensions of the expression.
bool in_bounds(Args... args) const
Returns true only if the the specified position is a valid entry in the expression.
const_reference back() const
Returns a constant reference to last the element of the expression.
layout_type layout() const noexcept
Returns the layout of the xtrided_view_base.
const inner_shape_type & shape() const noexcept
Returns the shape of the xtrided_view_base.
Base class for multidimensional iterable expressions.
layout_type layout() const noexcept
Returns the layout of the xtrided_view_base.
bool broadcast_shape(O &shape, bool reuse_cache=false) const
Broadcast the shape of the view to the specified parameter.
const inner_shape_type & shape() const noexcept
Returns the shape of the xtrided_view_base.
storage_type & storage() noexcept
Returns a reference to the buffer containing the elements of the view.
xexpression_type & expression() noexcept
Returns a reference to the underlying expression of the view.
Implementation of the xsemantic_base interface for multidimensional views.
auto strides(const E &e, stride_type type=stride_type::normal) noexcept
Get strides of an object.
standard mathematical functions for xexpressions
bool operator==(const xaxis_iterator< CT > &lhs, const xaxis_iterator< CT > &rhs)
Checks equality of the iterators.
bool operator!=(const xaxis_iterator< CT > &lhs, const xaxis_iterator< CT > &rhs)
Checks inequality of the iterators.