10#ifndef XTENSOR_STRIDED_VIEW_HPP
11#define XTENSOR_STRIDED_VIEW_HPP
19#include <xtl/xsequence.hpp>
21#include "../containers/xstorage.hpp"
22#include "../core/xexpression.hpp"
23#include "../core/xiterable.hpp"
24#include "../core/xlayout.hpp"
25#include "../core/xsemantic.hpp"
26#include "../utils/xutils.hpp"
27#include "../views/xstrided_view_base.hpp"
37 template <
class Tag,
class CT,
class S, layout_type L,
class FST>
40 template <
class CT,
class S, layout_type L,
class FST>
46 template <
class CT,
class S, layout_type L,
class FST>
51 template <
class CT,
class S, layout_type L,
class FST>
55 template <layout_type L1, layout_type L2,
class T>
58 using type = std::conditional_t<L1 == L2 && L1 != layout_type::dynamic, xcontiguous_iterable<T>,
xiterable<T>>;
61 template <layout_type L1, layout_type L2,
class T>
62 using select_iterable_base_t =
typename select_iterable_base<L1, L2, T>::type;
65 template <
class CT,
class S, layout_type L,
class FST>
68 template <
class CT,
class S, layout_type L,
class FST>
71 using xexpression_type = std::decay_t<CT>;
72 using undecay_expression = CT;
73 using reference = inner_reference_t<undecay_expression>;
74 using const_reference =
typename xexpression_type::const_reference;
75 using size_type =
typename xexpression_type::size_type;
76 using shape_type = std::decay_t<S>;
77 using undecay_shape = S;
78 using storage_getter = FST;
79 using inner_storage_type =
typename storage_getter::type;
80 using temporary_type =
typename detail::xtype_for_shape<
81 S>::template type<typename xexpression_type::value_type, xexpression_type::static_layout>;
82 using storage_type = std::remove_reference_t<inner_storage_type>;
86 template <
class CT,
class S, layout_type L,
class FST>
89 using inner_shape_type = std::decay_t<S>;
90 using inner_strides_type = get_strides_t<inner_shape_type>;
91 using inner_backstrides_type_type = inner_strides_type;
93 using const_stepper = std::conditional_t<
98 using stepper = std::conditional_t<
104 template <
class CT,
class S, layout_type L,
class FST,
class RHS>
127 template <
class CT,
class S, layout_type L = layout_type::dynamic,
class FST = detail::flat_storage_getter<CT, XTENSOR_DEFAULT_TRAVERSAL>>
129 :
public xview_semantic<xstrided_view<CT, S, L, FST>>,
130 public select_iterable_base_t<L, std::decay_t<CT>::static_layout, xstrided_view<CT, S, L, FST>>,
132 public extension::xstrided_view_base_t<CT, S, L, FST>
138 using semantic_base = xview_semantic<self_type>;
139 using extension_base = extension::xstrided_view_base_t<CT, S, L, FST>;
140 using expression_tag =
typename extension_base::expression_tag;
142 using xexpression_type =
typename base_type::xexpression_type;
143 using base_type::is_const;
145 using value_type =
typename base_type::value_type;
146 using reference =
typename base_type::reference;
147 using const_reference =
typename base_type::const_reference;
148 using pointer =
typename base_type::pointer;
149 using const_pointer =
typename base_type::const_pointer;
150 using size_type =
typename base_type::size_type;
151 using difference_type =
typename base_type::difference_type;
153 using inner_storage_type =
typename base_type::inner_storage_type;
154 using storage_type =
typename base_type::storage_type;
155 using linear_iterator =
typename storage_type::iterator;
156 using const_linear_iterator =
typename storage_type::const_iterator;
157 using reverse_linear_iterator = std::reverse_iterator<linear_iterator>;
158 using const_reverse_linear_iterator = std::reverse_iterator<const_linear_iterator>;
160 using iterable_base = select_iterable_base_t<L, xexpression_type::static_layout, self_type>;
161 using inner_shape_type =
typename base_type::inner_shape_type;
162 using inner_strides_type =
typename base_type::inner_strides_type;
163 using inner_backstrides_type =
typename base_type::inner_backstrides_type;
164 using shape_type =
typename base_type::shape_type;
165 using strides_type =
typename base_type::strides_type;
166 using backstrides_type =
typename base_type::backstrides_type;
168 using stepper =
typename iterable_base::stepper;
169 using const_stepper =
typename iterable_base::const_stepper;
171 using base_type::contiguous_layout;
172 using base_type::static_layout;
175 using base_index_type = xindex_type_t<shape_type>;
177 using data_alignment = xt_simd::container_alignment_t<storage_type>;
178 using simd_type = xt_simd::simd_type<value_type>;
179 using simd_value_type = xt_simd::simd_type<value_type>;
180 using bool_load_type =
typename base_type::bool_load_type;
187 && std::is_lvalue_reference_v<
188 decltype(std::declval<const storage_type&>()[0])>;
190 template <
class CTA,
class SA>
195 self_type& operator=(
const self_type&);
201 disable_xexpression<E, self_type>& operator=(
const E& e);
205 using base_type::is_contiguous;
211 using base_type::operator();
214 using base_type::operator[];
227 linear_iterator linear_begin();
228 linear_iterator linear_end();
229 const_linear_iterator linear_begin()
const;
230 const_linear_iterator linear_end()
const;
231 const_linear_iterator linear_cbegin()
const;
232 const_linear_iterator linear_cend()
const;
234 reverse_linear_iterator linear_rbegin();
235 reverse_linear_iterator linear_rend();
236 const_reverse_linear_iterator linear_rbegin()
const;
237 const_reverse_linear_iterator linear_rend()
const;
238 const_reverse_linear_iterator linear_crbegin()
const;
239 const_reverse_linear_iterator linear_crend()
const;
241 template <
class ST,
class STEP = stepper>
242 disable_indexed_stepper_t<STEP> stepper_begin(
const ST&
shape);
243 template <
class ST,
class STEP = stepper>
244 disable_indexed_stepper_t<STEP> stepper_end(
const ST&
shape,
layout_type l);
246 template <
class ST,
class STEP = stepper>
247 enable_indexed_stepper_t<STEP> stepper_begin(
const ST&
shape);
248 template <
class ST,
class STEP = stepper>
251 template <
class ST,
class STEP = const_stepper>
252 disable_indexed_stepper_t<STEP> stepper_begin(
const ST&
shape)
const;
253 template <
class ST,
class STEP = const_stepper>
254 disable_indexed_stepper_t<STEP> stepper_end(
const ST&
shape,
layout_type l)
const;
256 template <
class ST,
class STEP = const_stepper>
257 enable_indexed_stepper_t<STEP> stepper_begin(
const ST&
shape)
const;
258 template <
class ST,
class STEP = const_stepper>
259 enable_indexed_stepper_t<STEP> stepper_end(
const ST&
shape,
layout_type l)
const;
261 template <
class requested_type>
262 using simd_return_type = xt_simd::simd_return_type<value_type, requested_type>;
264 template <
class align,
class simd>
265 void store_simd(size_type i,
const simd& e)
266 requires provides_simd_interface;
268 template <class align, class requested_type = value_type, std::size_t N = xt_simd::simd_traits<requested_type>::size>
269 simd_return_type<requested_type> load_simd(size_type i)
const
270 requires provides_simd_interface;
272 reference data_element(size_type i);
273 const_reference data_element(size_type i)
const;
275 reference flat(size_type i);
276 const_reference flat(size_type i)
const;
278 using container_iterator = std::
279 conditional_t<is_const, typename storage_type::const_iterator, typename storage_type::iterator>;
280 using const_container_iterator =
typename storage_type::const_iterator;
286 rebind_t<E> build_view(E&& e)
const;
290 container_iterator data_xbegin() noexcept;
291 const_container_iterator data_xbegin() const noexcept;
292 container_iterator data_xend(
layout_type l, size_type offset) noexcept;
293 const_container_iterator data_xend(
layout_type l, size_type offset) const noexcept;
296 It data_xbegin_impl(It begin) const noexcept;
299 It data_xend_impl(It end,
layout_type l, size_type offset) const noexcept;
301 void assign_temporary_impl(temporary_type&& tmp);
303 using base_type::set_offset;
306 friend class xstepper;
307 friend class xview_semantic<self_type>;
311 friend class xaxis_iterator;
313 friend class xaxis_slice_iterator;
321 using xstrided_slice = std::variant<
333 xrange_adaptor<placeholders::xtuph, placeholders::xtuph, placeholders::xtuph>,
371 template <class CT, class S,
layout_type L, class FST>
372 template <class CTA, class SA>
380 : base_type(std::forward<CTA>(e), std::forward<SA>(
shape), std::move(
strides), offset,
layout)
386 template <
class CT,
class S, layout_type L,
class FST>
387 inline auto xstrided_view<CT, S, L, FST>::operator=(
const self_type& rhs) -> self_type&
400 template <
class CT,
class S, layout_type L,
class FST>
402 inline auto xstrided_view<CT, S, L, FST>::operator=(
const xexpression<E>& e) -> self_type&
404 return semantic_base::operator=(e);
409 template <
class CT,
class S, layout_type L,
class FST>
411 inline auto xstrided_view<CT, S, L, FST>::operator=(
const E& e) -> disable_xexpression<E, self_type>&
417 namespace xstrided_view_detail
419 template <
class V,
class T>
420 inline void run_assign_temporary_impl(V& v,
const T& t, std::true_type )
422 strided_loop_assigner<true>::run(v, t);
425 template <
class V,
class T>
427 run_assign_temporary_impl(V& v,
const T& t, std::false_type )
429 std::copy(t.cbegin(), t.cend(), v.begin());
433 template <
class CT,
class S, layout_type L,
class FST>
437 fast_assign = xassign_traits<xstrided_view<CT, S, L, FST>, temporary_type>::simd_strided_assign();
438 xstrided_view_detail::run_assign_temporary_impl(*
this, tmp, std::integral_constant<bool, fast_assign>{});
450 template <
class CT,
class S, layout_type L,
class FST>
456 std::fill(this->linear_begin(), this->linear_end(), value);
460 std::fill(this->begin(), this->end(), value);
466 template <
class CT,
class S, layout_type L,
class FST>
467 inline auto xstrided_view<CT, S, L, FST>::data_element(size_type i) -> reference
472 template <
class CT,
class S, layout_type L,
class FST>
473 inline auto xstrided_view<CT, S, L, FST>::data_element(size_type i)
const -> const_reference
478 template <
class CT,
class S, layout_type L,
class FST>
484 template <
class CT,
class S, layout_type L,
class FST>
490 template <
class CT,
class S, layout_type L,
class FST>
496 template <
class CT,
class S, layout_type L,
class FST>
502 template <
class CT,
class S, layout_type L,
class FST>
505 return this->linear_cbegin();
508 template <
class CT,
class S, layout_type L,
class FST>
511 return this->linear_cend();
514 template <
class CT,
class S, layout_type L,
class FST>
520 template <
class CT,
class S, layout_type L,
class FST>
526 template <
class CT,
class S, layout_type L,
class FST>
529 return reverse_linear_iterator(this->linear_begin());
532 template <
class CT,
class S, layout_type L,
class FST>
535 return reverse_linear_iterator(this->linear_end());
538 template <
class CT,
class S, layout_type L,
class FST>
541 return this->linear_crbegin();
544 template <
class CT,
class S, layout_type L,
class FST>
547 return this->linear_crend();
550 template <
class CT,
class S, layout_type L,
class FST>
553 return const_reverse_linear_iterator(this->linear_cbegin());
556 template <
class CT,
class S, layout_type L,
class FST>
559 return const_reverse_linear_iterator(this->linear_cend());
566 template <
class CT,
class S, layout_type L,
class FST>
567 template <
class ST,
class STEP>
571 return stepper(
this, data_xbegin(), offset);
574 template <
class CT,
class S, layout_type L,
class FST>
575 template <
class ST,
class STEP>
577 -> disable_indexed_stepper_t<STEP>
580 return stepper(
this, data_xend(l, offset), offset);
583 template <
class CT,
class S, layout_type L,
class FST>
584 template <
class ST,
class STEP>
588 return stepper(
this, offset);
591 template <
class CT,
class S, layout_type L,
class FST>
592 template <
class ST,
class STEP>
594 -> enable_indexed_stepper_t<STEP>
597 return stepper(
this, offset,
true);
600 template <
class CT,
class S, layout_type L,
class FST>
601 template <
class ST,
class STEP>
603 -> disable_indexed_stepper_t<STEP>
606 return const_stepper(
this, data_xbegin(), offset);
609 template <
class CT,
class S, layout_type L,
class FST>
610 template <
class ST,
class STEP>
612 -> disable_indexed_stepper_t<STEP>
615 return const_stepper(
this, data_xend(l, offset), offset);
618 template <
class CT,
class S, layout_type L,
class FST>
619 template <
class ST,
class STEP>
621 -> enable_indexed_stepper_t<STEP>
624 return const_stepper(
this, offset);
627 template <
class CT,
class S, layout_type L,
class FST>
628 template <
class ST,
class STEP>
630 -> enable_indexed_stepper_t<STEP>
633 return const_stepper(
this, offset,
true);
636 template <
class CT,
class S, layout_type L,
class FST>
640 return begin +
static_cast<std::ptrdiff_t
>(this->
data_offset());
643 template <
class CT,
class S, layout_type L,
class FST>
648 return strided_data_end(*
this, begin + std::ptrdiff_t(this->
data_offset()), l, offset);
651 template <
class CT,
class S, layout_type L,
class FST>
654 return data_xbegin_impl(this->
storage().begin());
657 template <
class CT,
class S, layout_type L,
class FST>
660 return data_xbegin_impl(this->
storage().cbegin());
663 template <
class CT,
class S, layout_type L,
class FST>
665 -> container_iterator
667 return data_xend_impl(this->
storage().begin(), l, offset);
670 template <
class CT,
class S, layout_type L,
class FST>
672 -> const_container_iterator
674 return data_xend_impl(this->
storage().cbegin(), l, offset);
677 template <
class CT,
class S, layout_type L,
class FST>
678 template <
class alignment,
class simd>
680 requires provides_simd_interface
682 using align_mode = driven_align_mode_t<alignment, data_alignment>;
683 xt_simd::store_as(&(
storage()[i]), e, align_mode());
686 template <
class CT,
class S, layout_type L,
class FST>
687 template <
class alignment,
class requested_type, std::
size_t N>
689 requires provides_simd_interface
691 using align_mode = driven_align_mode_t<alignment, data_alignment>;
692 return xt_simd::load_as<requested_type>(&(
storage()[i]), align_mode());
695 template <
class CT,
class S, layout_type L,
class FST>
699 inner_shape_type sh(this->
shape());
700 inner_strides_type str(this->
strides());
730 template <layout_type L,
class E,
class S,
class X>
734 return view_type(std::forward<E>(e), std::forward<S>(shape), std::forward<X>(
strides), offset,
layout);
739 struct no_adj_strides_policy
743 inline void resize(std::size_t)
747 inline void set_fake_slice(std::size_t)
751 template <
class ST,
class S>
753 const xstrided_slice_vector& ,
795 detail::strided_view_args<detail::no_adj_strides_policy> args;
798 detail::get_strides<XTENSOR_DEFAULT_TRAVERSAL>(e),
799 detail::get_offset<XTENSOR_DEFAULT_TRAVERSAL>(e),
806 std::move(args.new_shape),
807 std::move(args.new_strides),
815 template <
typename S>
818 template <std::size_t... X>
819 struct rebind_shape<
xt::fixed_shape<X...>>
827 using type = rebind_container_t<size_t, S>;
831 inline void recalculate_shape_impl(S& shape,
size_t size)
833 if constexpr (std::is_signed_v<get_value_type_t<typename std::decay<S>::type>>)
835 using value_type = get_value_type_t<typename std::decay_t<S>>;
836 XTENSOR_ASSERT(std::count(shape.cbegin(), shape.cend(), -1) <= 1);
837 auto iter = std::find(shape.begin(), shape.end(), -1);
838 if (iter != std::end(shape))
840 const auto total = std::accumulate(shape.cbegin(), shape.cend(), -1, std::multiplies<int>{});
841 const auto missing_dimension = size /
static_cast<size_t>(total);
842 (*iter) =
static_cast<value_type
>(missing_dimension);
848 inline auto recalculate_shape(S&& shape,
size_t size)
850 return recalculate_shape_impl(shape, size);
854 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL,
class E,
class S>
855 inline auto reshape_view(E&& e, S&&
shape)
859 "traversal has to be row or column major"
862 using shape_type = std::decay_t<
decltype(
shape)>;
863 using unsigned_shape_type =
typename detail::rebind_shape<shape_type>::type;
864 get_strides_t<unsigned_shape_type>
strides;
866 detail::recalculate_shape(
shape, e.size());
869 constexpr auto computed_layout = std::decay_t<E>::static_layout == L ? L :
layout_type::dynamic;
874 detail::flat_adaptor_getter<xclosure_t<E>, L>>;
877 xtl::forward_sequence<unsigned_shape_type, S>(
shape),
897 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL,
class E,
class S>
900 return reshape_view<L>(std::forward<E>(e), std::forward<S>(shape));
903 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL,
class E,
class I, std::
size_t N>
906 using shape_type = std::array<std::size_t, N>;
907 return reshape_view<L>(std::forward<E>(e), xtl::forward_sequence<shape_type,
decltype(
shape)>(
shape), order);
910 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL,
class E,
class I, std::
size_t N>
911 inline auto reshape_view(E&& e,
const I (&
shape)[N])
913 using shape_type = std::array<I, N>;
914 return reshape_view<L>(std::forward<E>(e), xtl::forward_sequence<shape_type,
decltype(
shape)>(
shape));
Fixed shape implementation for compile time defined arrays.
Base class for implementation of common expression access methods.
Base class for implementation of common expression constant access methods.
size_type size() const noexcept(noexcept(derived_cast().shape()))
size_type dimension() const noexcept
const_reference at(Args... args) const
Base class for xexpressions.
Base class for multidimensional iterable expressions.
layout_type layout() const noexcept
reference unchecked(Args... args)
xstrided_view_base(CTA &&e, SA &&shape, strides_type &&strides, size_type offset, layout_type layout) noexcept
Constructs an xstrided_view_base.
bool has_linear_assign(const O &strides) const noexcept
const inner_strides_type & strides() const noexcept
bool broadcast_shape(O &shape, bool reuse_cache=false) const
const inner_backstrides_type & backstrides() const noexcept
const inner_shape_type & shape() const noexcept
size_type data_offset() const noexcept
storage_type & storage() noexcept
xexpression_type & expression() noexcept
reference element(It first, It last)
View of an xexpression using strides.
void fill(const T &value)
Fills the view with the given value.
storage_type & storage() noexcept
Returns a reference to the buffer containing the elements of the view.
size_type data_offset() const noexcept
Returns the offset to the first element in the view.
const inner_shape_type & shape() const noexcept
self_type & operator=(const xexpression< E > &e)
The extended assignment operator.
layout_type layout() const noexcept
xstrided_view(CTA &&e, SA &&shape, strides_type &&strides, std::size_t offset, layout_type layout) noexcept
Constructs an xstrided_view.
const inner_strides_type & strides() const noexcept
derived_type & assign_temporary(temporary_type &&)
Assigns the temporary tmp to *this.
std::size_t compute_strides(const shape_type &shape, layout_type l, strides_type &strides)
Compute the strides given the shape and the layout of an array.
auto strides(const E &e, stride_type type=stride_type::normal) noexcept
Get strides of an object.
standard mathematical functions for xexpressions
std::vector< xstrided_slice< std::ptrdiff_t > > xstrided_slice_vector
vector of slices used to build a xstrided_view
auto strided_view(E &&e, S &&shape, X &&stride, std::size_t offset=0, layout_type layout=L) noexcept
Construct a strided view from an xexpression, shape, strides and offset.