xtensor
 
Loading...
Searching...
No Matches
xstrided_view.hpp
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
10#ifndef XTENSOR_STRIDED_VIEW_HPP
11#define XTENSOR_STRIDED_VIEW_HPP
12
13#include <algorithm>
14#include <cstddef>
15#include <tuple>
16#include <type_traits>
17#include <utility>
18#include <variant>
19
20#include <xtl/xsequence.hpp>
21
22#include "../containers/xstorage.hpp"
23#include "../core/xexpression.hpp"
24#include "../core/xiterable.hpp"
25#include "../core/xlayout.hpp"
26#include "../core/xsemantic.hpp"
27#include "../utils/xutils.hpp"
28#include "../views/xstrided_view_base.hpp"
29
30namespace xt
31{
32 /***************************
33 * xstrided_view extension *
34 ***************************/
35
36 namespace extension
37 {
38 template <class Tag, class CT, class S, layout_type L, class FST>
40
41 template <class CT, class S, layout_type L, class FST>
43 {
44 using type = xtensor_empty_base;
45 };
46
47 template <class CT, class S, layout_type L, class FST>
48 struct xstrided_view_base : xstrided_view_base_impl<xexpression_tag_t<CT>, CT, S, L, FST>
49 {
50 };
51
52 template <class CT, class S, layout_type L, class FST>
53 using xstrided_view_base_t = typename xstrided_view_base<CT, S, L, FST>::type;
54 }
55
56 template <layout_type L1, layout_type L2, class T>
58 {
59 using type = std::conditional_t<L1 == L2 && L1 != layout_type::dynamic, xcontiguous_iterable<T>, xiterable<T>>;
60 };
61
62 template <layout_type L1, layout_type L2, class T>
63 using select_iterable_base_t = typename select_iterable_base<L1, L2, T>::type;
64
65
66 template <class CT, class S, layout_type L, class FST>
67 class xstrided_view;
68
69 template <class CT, class S, layout_type L, class FST>
71 {
72 using xexpression_type = std::decay_t<CT>;
73 using undecay_expression = CT;
74 using reference = inner_reference_t<undecay_expression>;
75 using const_reference = typename xexpression_type::const_reference;
76 using size_type = typename xexpression_type::size_type;
77 using shape_type = std::decay_t<S>;
78 using undecay_shape = S;
79 using storage_getter = FST;
80 using inner_storage_type = typename storage_getter::type;
81 using temporary_type = typename detail::xtype_for_shape<
82 S>::template type<typename xexpression_type::value_type, xexpression_type::static_layout>;
83 using storage_type = std::remove_reference_t<inner_storage_type>;
84 static constexpr layout_type layout = L;
85 };
86
87 template <class CT, class S, layout_type L, class FST>
88 struct xiterable_inner_types<xstrided_view<CT, S, L, FST>>
89 {
90 using inner_shape_type = std::decay_t<S>;
91 using inner_strides_type = get_strides_t<inner_shape_type>;
92 using inner_backstrides_type_type = inner_strides_type;
93
94 using const_stepper = std::conditional_t<
98
99 using stepper = std::conditional_t<
103 };
104
105 template <class CT, class S, layout_type L, class FST, class RHS>
106 struct can_assign<xstrided_view<CT, S, L, FST>, RHS> : can_assign<CT, RHS>
107 {
108 };
109
110 /*****************
111 * xstrided_view *
112 *****************/
113
128 template <class CT, class S, layout_type L = layout_type::dynamic, class FST = detail::flat_storage_getter<CT, XTENSOR_DEFAULT_TRAVERSAL>>
130 : public xview_semantic<xstrided_view<CT, S, L, FST>>,
131 public select_iterable_base_t<L, std::decay_t<CT>::static_layout, xstrided_view<CT, S, L, FST>>,
132 private xstrided_view_base<xstrided_view<CT, S, L, FST>>,
133 public extension::xstrided_view_base_t<CT, S, L, FST>
134 {
135 public:
136
137 using self_type = xstrided_view<CT, S, L, FST>;
138 using base_type = xstrided_view_base<self_type>;
139 using semantic_base = xview_semantic<self_type>;
140 using extension_base = extension::xstrided_view_base_t<CT, S, L, FST>;
141 using expression_tag = typename extension_base::expression_tag;
142
143 using xexpression_type = typename base_type::xexpression_type;
144 using base_type::is_const;
145
146 using value_type = typename base_type::value_type;
147 using reference = typename base_type::reference;
148 using const_reference = typename base_type::const_reference;
149 using pointer = typename base_type::pointer;
150 using const_pointer = typename base_type::const_pointer;
151 using size_type = typename base_type::size_type;
152 using difference_type = typename base_type::difference_type;
153
154 using inner_storage_type = typename base_type::inner_storage_type;
155 using storage_type = typename base_type::storage_type;
156 using linear_iterator = typename storage_type::iterator;
157 using const_linear_iterator = typename storage_type::const_iterator;
158 using reverse_linear_iterator = std::reverse_iterator<linear_iterator>;
159 using const_reverse_linear_iterator = std::reverse_iterator<const_linear_iterator>;
160
161 using iterable_base = select_iterable_base_t<L, xexpression_type::static_layout, self_type>;
162 using inner_shape_type = typename base_type::inner_shape_type;
163 using inner_strides_type = typename base_type::inner_strides_type;
164 using inner_backstrides_type = typename base_type::inner_backstrides_type;
165 using shape_type = typename base_type::shape_type;
166 using strides_type = typename base_type::strides_type;
167 using backstrides_type = typename base_type::backstrides_type;
168
169 using stepper = typename iterable_base::stepper;
170 using const_stepper = typename iterable_base::const_stepper;
171
172 using base_type::contiguous_layout;
173 using base_type::static_layout;
174
175 using temporary_type = typename xcontainer_inner_types<self_type>::temporary_type;
176 using base_index_type = xindex_type_t<shape_type>;
177
178 using data_alignment = xt_simd::container_alignment_t<storage_type>;
179 using simd_type = xt_simd::simd_type<value_type>;
180 using simd_value_type = xt_simd::simd_type<value_type>;
181 using bool_load_type = typename base_type::bool_load_type;
182
183 static constexpr bool provides_simd_interface = has_simd_interface<xexpression_type>::value
184 && L != layout_type::dynamic;
185
186 template <class CTA, class SA>
187 xstrided_view(CTA&& e, SA&& shape, strides_type&& strides, std::size_t offset, layout_type layout) noexcept;
188
189 xstrided_view(const xstrided_view& rhs) = default;
190
191 self_type& operator=(const self_type&);
192
193 template <class E>
194 self_type& operator=(const xexpression<E>& e);
195
196 template <class E>
197 disable_xexpression<E, self_type>& operator=(const E& e);
198
201 using base_type::is_contiguous;
202 using base_type::layout;
203 using base_type::shape;
204 using base_type::size;
205 using base_type::strides;
206
207 using base_type::operator();
208 using base_type::at;
209 using base_type::unchecked;
210 using base_type::operator[];
211 using base_type::data;
213 using base_type::element;
215 using base_type::storage;
216
219
220 template <class T>
221 void fill(const T& value);
222
223 linear_iterator linear_begin();
224 linear_iterator linear_end();
225 const_linear_iterator linear_begin() const;
226 const_linear_iterator linear_end() const;
227 const_linear_iterator linear_cbegin() const;
228 const_linear_iterator linear_cend() const;
229
230 reverse_linear_iterator linear_rbegin();
231 reverse_linear_iterator linear_rend();
232 const_reverse_linear_iterator linear_rbegin() const;
233 const_reverse_linear_iterator linear_rend() const;
234 const_reverse_linear_iterator linear_crbegin() const;
235 const_reverse_linear_iterator linear_crend() const;
236
237 template <class ST, class STEP = stepper>
238 disable_indexed_stepper_t<STEP> stepper_begin(const ST& shape);
239 template <class ST, class STEP = stepper>
240 disable_indexed_stepper_t<STEP> stepper_end(const ST& shape, layout_type l);
241
242 template <class ST, class STEP = stepper>
243 enable_indexed_stepper_t<STEP> stepper_begin(const ST& shape);
244 template <class ST, class STEP = stepper>
245 enable_indexed_stepper_t<STEP> stepper_end(const ST& shape, layout_type l);
246
247 template <class ST, class STEP = const_stepper>
248 disable_indexed_stepper_t<STEP> stepper_begin(const ST& shape) const;
249 template <class ST, class STEP = const_stepper>
250 disable_indexed_stepper_t<STEP> stepper_end(const ST& shape, layout_type l) const;
251
252 template <class ST, class STEP = const_stepper>
253 enable_indexed_stepper_t<STEP> stepper_begin(const ST& shape) const;
254 template <class ST, class STEP = const_stepper>
255 enable_indexed_stepper_t<STEP> stepper_end(const ST& shape, layout_type l) const;
256
257 template <class requested_type>
258 using simd_return_type = xt_simd::simd_return_type<value_type, requested_type>;
259
260 template <class align, class simd>
261 void store_simd(size_type i, const simd& e)
262 requires provides_simd_interface;
263
264 template <class align, class requested_type = value_type, std::size_t N = xt_simd::simd_traits<requested_type>::size>
265 simd_return_type<requested_type> load_simd(size_type i) const
266 requires provides_simd_interface;
267
268 reference data_element(size_type i);
269 const_reference data_element(size_type i) const;
270
271 reference flat(size_type i);
272 const_reference flat(size_type i) const;
273
274 using container_iterator = std::
275 conditional_t<is_const, typename storage_type::const_iterator, typename storage_type::iterator>;
276 using const_container_iterator = typename storage_type::const_iterator;
277
278 template <class E>
280
281 template <class E>
282 rebind_t<E> build_view(E&& e) const;
283
284 private:
285
286 container_iterator data_xbegin() noexcept;
287 const_container_iterator data_xbegin() const noexcept;
288 container_iterator data_xend(layout_type l, size_type offset) noexcept;
289 const_container_iterator data_xend(layout_type l, size_type offset) const noexcept;
290
291 template <class It>
292 It data_xbegin_impl(It begin) const noexcept;
293
294 template <class It>
295 It data_xend_impl(It end, layout_type l, size_type offset) const noexcept;
296
297 void assign_temporary_impl(temporary_type&& tmp);
298
299 using base_type::set_offset;
300
301 template <class C>
302 friend class xstepper;
303 friend class xview_semantic<self_type>;
304 friend class xaccessible<self_type>;
305 friend class xconst_accessible<self_type>;
306 template <class D>
307 friend class xaxis_iterator;
308 template <class D>
309 friend class xaxis_slice_iterator;
310 };
311
312 /**************************
313 * xstrided_view builders *
314 **************************/
315
316 template <class T>
317 using xstrided_slice = std::variant<
318 T,
319
320 xrange_adaptor<placeholders::xtuph, T, T>,
321 xrange_adaptor<T, placeholders::xtuph, T>,
322 xrange_adaptor<T, T, placeholders::xtuph>,
323
324 xrange_adaptor<T, placeholders::xtuph, placeholders::xtuph>,
325 xrange_adaptor<placeholders::xtuph, T, placeholders::xtuph>,
326 xrange_adaptor<placeholders::xtuph, placeholders::xtuph, T>,
327
328 xrange_adaptor<T, T, T>,
329 xrange_adaptor<placeholders::xtuph, placeholders::xtuph, placeholders::xtuph>,
330
331 xrange<T>,
333
334 xall_tag,
337
342 using xstrided_slice_vector = std::vector<xstrided_slice<std::ptrdiff_t>>;
343
344 template <layout_type L = layout_type::dynamic, class E, class S, class X>
345 auto strided_view(E&& e, S&& shape, X&& stride, std::size_t offset = 0, layout_type layout = L) noexcept;
346
347 template <class E>
348 auto strided_view(E&& e, const xstrided_slice_vector& slices);
349
350 /********************************
351 * xstrided_view implementation *
352 ********************************/
353
358
367 template <class CT, class S, layout_type L, class FST>
368 template <class CTA, class SA>
369 inline xstrided_view<CT, S, L, FST>::xstrided_view(
370 CTA&& e,
371 SA&& shape,
372 strides_type&& strides,
373 std::size_t offset,
375 ) noexcept
376 : base_type(std::forward<CTA>(e), std::forward<SA>(shape), std::move(strides), offset, layout)
377 {
378 }
379
381
382 template <class CT, class S, layout_type L, class FST>
383 inline auto xstrided_view<CT, S, L, FST>::operator=(const self_type& rhs) -> self_type&
384 {
385 temporary_type tmp(rhs);
386 return this->assign_temporary(std::move(tmp));
387 }
388
393
396 template <class CT, class S, layout_type L, class FST>
397 template <class E>
398 inline auto xstrided_view<CT, S, L, FST>::operator=(const xexpression<E>& e) -> self_type&
399 {
400 return semantic_base::operator=(e);
401 }
402
404
405 template <class CT, class S, layout_type L, class FST>
406 template <class E>
407 inline auto xstrided_view<CT, S, L, FST>::operator=(const E& e) -> disable_xexpression<E, self_type>&
408 {
409 this->fill(e);
410 return *this;
411 }
412
413 namespace xstrided_view_detail
414 {
415 template <class V, class T>
416 inline void run_assign_temporary_impl(V& v, const T& t, std::true_type /* enable strided assign */)
417 {
418 strided_loop_assigner<true>::run(v, t);
419 }
420
421 template <class V, class T>
422 inline void
423 run_assign_temporary_impl(V& v, const T& t, std::false_type /* fallback to iterator assign */)
424 {
425 std::copy(t.cbegin(), t.cend(), v.begin());
426 }
427 }
428
429 template <class CT, class S, layout_type L, class FST>
430 inline void xstrided_view<CT, S, L, FST>::assign_temporary_impl(temporary_type&& tmp)
431 {
432 constexpr bool
433 fast_assign = xassign_traits<xstrided_view<CT, S, L, FST>, temporary_type>::simd_strided_assign();
434 xstrided_view_detail::run_assign_temporary_impl(*this, tmp, std::integral_constant<bool, fast_assign>{});
435 }
436
441
446 template <class CT, class S, layout_type L, class FST>
447 template <class T>
448 inline void xstrided_view<CT, S, L, FST>::fill(const T& value)
449 {
451 {
452 std::fill(this->linear_begin(), this->linear_end(), value);
453 }
454 else
455 {
456 std::fill(this->begin(), this->end(), value);
457 }
458 }
459
461
462 template <class CT, class S, layout_type L, class FST>
463 inline auto xstrided_view<CT, S, L, FST>::data_element(size_type i) -> reference
464 {
465 return storage()[i];
466 }
467
468 template <class CT, class S, layout_type L, class FST>
469 inline auto xstrided_view<CT, S, L, FST>::data_element(size_type i) const -> const_reference
470 {
471 return storage()[i];
472 }
473
474 template <class CT, class S, layout_type L, class FST>
475 inline auto xstrided_view<CT, S, L, FST>::flat(size_type i) -> reference
476 {
477 return storage()[i];
478 }
479
480 template <class CT, class S, layout_type L, class FST>
481 inline auto xstrided_view<CT, S, L, FST>::flat(size_type i) const -> const_reference
482 {
483 return storage()[i];
484 }
485
486 template <class CT, class S, layout_type L, class FST>
487 inline auto xstrided_view<CT, S, L, FST>::linear_begin() -> linear_iterator
488 {
489 return this->storage().begin() + static_cast<std::ptrdiff_t>(data_offset());
490 }
491
492 template <class CT, class S, layout_type L, class FST>
493 inline auto xstrided_view<CT, S, L, FST>::linear_end() -> linear_iterator
494 {
495 return this->storage().begin() + static_cast<std::ptrdiff_t>(data_offset() + size());
496 }
497
498 template <class CT, class S, layout_type L, class FST>
499 inline auto xstrided_view<CT, S, L, FST>::linear_begin() const -> const_linear_iterator
500 {
501 return this->linear_cbegin();
502 }
503
504 template <class CT, class S, layout_type L, class FST>
505 inline auto xstrided_view<CT, S, L, FST>::linear_end() const -> const_linear_iterator
506 {
507 return this->linear_cend();
508 }
509
510 template <class CT, class S, layout_type L, class FST>
511 inline auto xstrided_view<CT, S, L, FST>::linear_cbegin() const -> const_linear_iterator
512 {
513 return this->storage().cbegin() + static_cast<std::ptrdiff_t>(data_offset());
514 }
515
516 template <class CT, class S, layout_type L, class FST>
517 inline auto xstrided_view<CT, S, L, FST>::linear_cend() const -> const_linear_iterator
518 {
519 return this->storage().cbegin() + static_cast<std::ptrdiff_t>(data_offset() + size());
520 }
521
522 template <class CT, class S, layout_type L, class FST>
523 inline auto xstrided_view<CT, S, L, FST>::linear_rbegin() -> reverse_linear_iterator
524 {
525 return reverse_linear_iterator(this->linear_begin());
526 }
527
528 template <class CT, class S, layout_type L, class FST>
529 inline auto xstrided_view<CT, S, L, FST>::linear_rend() -> reverse_linear_iterator
530 {
531 return reverse_linear_iterator(this->linear_end());
532 }
533
534 template <class CT, class S, layout_type L, class FST>
535 inline auto xstrided_view<CT, S, L, FST>::linear_rbegin() const -> const_reverse_linear_iterator
536 {
537 return this->linear_crbegin();
538 }
539
540 template <class CT, class S, layout_type L, class FST>
541 inline auto xstrided_view<CT, S, L, FST>::linear_rend() const -> const_reverse_linear_iterator
542 {
543 return this->linear_crend();
544 }
545
546 template <class CT, class S, layout_type L, class FST>
547 inline auto xstrided_view<CT, S, L, FST>::linear_crbegin() const -> const_reverse_linear_iterator
548 {
549 return const_reverse_linear_iterator(this->linear_cbegin());
550 }
551
552 template <class CT, class S, layout_type L, class FST>
553 inline auto xstrided_view<CT, S, L, FST>::linear_crend() const -> const_reverse_linear_iterator
554 {
555 return const_reverse_linear_iterator(this->linear_cend());
556 }
557
558 /***************
559 * stepper api *
560 ***************/
561
562 template <class CT, class S, layout_type L, class FST>
563 template <class ST, class STEP>
564 inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) -> disable_indexed_stepper_t<STEP>
565 {
566 size_type offset = shape.size() - dimension();
567 return stepper(this, data_xbegin(), offset);
568 }
569
570 template <class CT, class S, layout_type L, class FST>
571 template <class ST, class STEP>
573 -> disable_indexed_stepper_t<STEP>
574 {
575 size_type offset = shape.size() - dimension();
576 return stepper(this, data_xend(l, offset), offset);
577 }
578
579 template <class CT, class S, layout_type L, class FST>
580 template <class ST, class STEP>
581 inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) -> enable_indexed_stepper_t<STEP>
582 {
583 size_type offset = shape.size() - dimension();
584 return stepper(this, offset);
585 }
586
587 template <class CT, class S, layout_type L, class FST>
588 template <class ST, class STEP>
590 -> enable_indexed_stepper_t<STEP>
591 {
592 size_type offset = shape.size() - dimension();
593 return stepper(this, offset, true);
594 }
595
596 template <class CT, class S, layout_type L, class FST>
597 template <class ST, class STEP>
598 inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) const
599 -> disable_indexed_stepper_t<STEP>
600 {
601 size_type offset = shape.size() - dimension();
602 return const_stepper(this, data_xbegin(), offset);
603 }
604
605 template <class CT, class S, layout_type L, class FST>
606 template <class ST, class STEP>
607 inline auto xstrided_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type l) const
608 -> disable_indexed_stepper_t<STEP>
609 {
610 size_type offset = shape.size() - dimension();
611 return const_stepper(this, data_xend(l, offset), offset);
612 }
613
614 template <class CT, class S, layout_type L, class FST>
615 template <class ST, class STEP>
616 inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) const
617 -> enable_indexed_stepper_t<STEP>
618 {
619 size_type offset = shape.size() - dimension();
620 return const_stepper(this, offset);
621 }
622
623 template <class CT, class S, layout_type L, class FST>
624 template <class ST, class STEP>
625 inline auto xstrided_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type /*l*/) const
626 -> enable_indexed_stepper_t<STEP>
627 {
628 size_type offset = shape.size() - dimension();
629 return const_stepper(this, offset, true);
630 }
631
632 template <class CT, class S, layout_type L, class FST>
633 template <class It>
634 inline It xstrided_view<CT, S, L, FST>::data_xbegin_impl(It begin) const noexcept
635 {
636 return begin + static_cast<std::ptrdiff_t>(this->data_offset());
637 }
638
639 template <class CT, class S, layout_type L, class FST>
640 template <class It>
641 inline It
642 xstrided_view<CT, S, L, FST>::data_xend_impl(It begin, layout_type l, size_type offset) const noexcept
643 {
644 return strided_data_end(*this, begin + std::ptrdiff_t(this->data_offset()), l, offset);
645 }
646
647 template <class CT, class S, layout_type L, class FST>
648 inline auto xstrided_view<CT, S, L, FST>::data_xbegin() noexcept -> container_iterator
649 {
650 return data_xbegin_impl(this->storage().begin());
651 }
652
653 template <class CT, class S, layout_type L, class FST>
654 inline auto xstrided_view<CT, S, L, FST>::data_xbegin() const noexcept -> const_container_iterator
655 {
656 return data_xbegin_impl(this->storage().cbegin());
657 }
658
659 template <class CT, class S, layout_type L, class FST>
660 inline auto xstrided_view<CT, S, L, FST>::data_xend(layout_type l, size_type offset) noexcept
661 -> container_iterator
662 {
663 return data_xend_impl(this->storage().begin(), l, offset);
664 }
665
666 template <class CT, class S, layout_type L, class FST>
667 inline auto xstrided_view<CT, S, L, FST>::data_xend(layout_type l, size_type offset) const noexcept
668 -> const_container_iterator
669 {
670 return data_xend_impl(this->storage().cbegin(), l, offset);
671 }
672
673 template <class CT, class S, layout_type L, class FST>
674 template <class alignment, class simd>
675 inline void xstrided_view<CT, S, L, FST>::store_simd(size_type i, const simd& e)
676 requires provides_simd_interface
677 {
678 using align_mode = driven_align_mode_t<alignment, data_alignment>;
679 xt_simd::store_as(&(storage()[i]), e, align_mode());
680 }
681
682 template <class CT, class S, layout_type L, class FST>
683 template <class alignment, class requested_type, std::size_t N>
684 inline auto xstrided_view<CT, S, L, FST>::load_simd(size_type i) const -> simd_return_type<requested_type>
685 requires provides_simd_interface
686 {
687 using align_mode = driven_align_mode_t<alignment, data_alignment>;
688 return xt_simd::load_as<requested_type>(&(storage()[i]), align_mode());
689 }
690
691 template <class CT, class S, layout_type L, class FST>
692 template <class E>
693 inline auto xstrided_view<CT, S, L, FST>::build_view(E&& e) const -> rebind_t<E>
694 {
695 inner_shape_type sh(this->shape());
696 inner_strides_type str(this->strides());
697 return rebind_t<E>(
698 std::forward<E>(e),
699 std::move(sh),
700 std::move(str),
702 this->layout()
703 );
704 }
705
706 /*****************************************
707 * xstrided_view builders implementation *
708 *****************************************/
709
726 template <layout_type L, class E, class S, class X>
727 inline auto strided_view(E&& e, S&& shape, X&& strides, std::size_t offset, layout_type layout) noexcept
728 {
729 using view_type = xstrided_view<xclosure_t<E>, S, L>;
730 return view_type(std::forward<E>(e), std::forward<S>(shape), std::forward<X>(strides), offset, layout);
731 }
732
733 namespace detail
734 {
735 struct no_adj_strides_policy
736 {
737 protected:
738
739 inline void resize(std::size_t)
740 {
741 }
742
743 inline void set_fake_slice(std::size_t)
744 {
745 }
746
747 template <class ST, class S>
748 bool fill_args(
749 const xstrided_slice_vector& /*slices*/,
750 std::size_t /*sl_idx*/,
751 std::size_t /*i*/,
752 std::size_t /*old_shape*/,
753 const ST& /*old_stride*/,
754 S& /*shape*/,
755 get_strides_t<S>& /*strides*/
756 )
757 {
758 return false;
759 }
760 };
761 }
762
788 template <class E>
789 inline auto strided_view(E&& e, const xstrided_slice_vector& slices)
790 {
791 detail::strided_view_args<detail::no_adj_strides_policy> args;
792 args.fill_args(
793 e.shape(),
794 detail::get_strides<XTENSOR_DEFAULT_TRAVERSAL>(e),
795 detail::get_offset<XTENSOR_DEFAULT_TRAVERSAL>(e),
796 e.layout(),
797 slices
798 );
799 using view_type = xstrided_view<xclosure_t<E>, decltype(args.new_shape)>;
800 return view_type(
801 std::forward<E>(e),
802 std::move(args.new_shape),
803 std::move(args.new_strides),
804 args.new_offset,
805 args.new_layout
806 );
807 }
808
809 namespace detail
810 {
811 template <typename S>
812 struct rebind_shape;
813
814 template <std::size_t... X>
815 struct rebind_shape<xt::fixed_shape<X...>>
816 {
817 using type = xt::fixed_shape<X...>;
818 };
819
820 template <class S>
821 struct rebind_shape
822 {
823 using type = rebind_container_t<size_t, S>;
824 };
825
826 template <class S>
827 inline void recalculate_shape_impl(S& shape, size_t size)
828 {
829 if constexpr (std::is_signed_v<get_value_type_t<typename std::decay<S>::type>>)
830 {
831 using value_type = get_value_type_t<typename std::decay_t<S>>;
832 XTENSOR_ASSERT(std::count(shape.cbegin(), shape.cend(), -1) <= 1);
833 auto iter = std::find(shape.begin(), shape.end(), -1);
834 if (iter != std::end(shape))
835 {
836 const auto total = std::accumulate(shape.cbegin(), shape.cend(), -1, std::multiplies<int>{});
837 const auto missing_dimension = size / total;
838 (*iter) = static_cast<value_type>(missing_dimension);
839 }
840 }
841 }
842
843 template <class S>
844 inline auto recalculate_shape(S&& shape, size_t size)
845 {
846 return recalculate_shape_impl(shape, size);
847 }
848 }
849
850 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class S>
851 inline auto reshape_view(E&& e, S&& shape)
852 {
853 static_assert(
855 "traversal has to be row or column major"
856 );
857
858 using shape_type = std::decay_t<decltype(shape)>;
859 using unsigned_shape_type = typename detail::rebind_shape<shape_type>::type;
860 get_strides_t<unsigned_shape_type> strides;
861
862 detail::recalculate_shape(shape, e.size());
863 xt::resize_container(strides, shape.size());
865 constexpr auto computed_layout = std::decay_t<E>::static_layout == L ? L : layout_type::dynamic;
866 using view_type = xstrided_view<
867 xclosure_t<E>,
868 unsigned_shape_type,
869 computed_layout,
870 detail::flat_adaptor_getter<xclosure_t<E>, L>>;
871 return view_type(
872 std::forward<E>(e),
873 xtl::forward_sequence<unsigned_shape_type, S>(shape),
874 std::move(strides),
875 0,
876 e.layout()
877 );
878 }
879
893 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class S>
894 inline auto reshape_view(E&& e, S&& shape, layout_type /*order*/)
895 {
896 return reshape_view<L>(std::forward<E>(e), std::forward<S>(shape));
897 }
898
899 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class I, std::size_t N>
900 inline auto reshape_view(E&& e, const I (&shape)[N], layout_type order)
901 {
902 using shape_type = std::array<std::size_t, N>;
903 return reshape_view<L>(std::forward<E>(e), xtl::forward_sequence<shape_type, decltype(shape)>(shape), order);
904 }
905
906 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class I, std::size_t N>
907 inline auto reshape_view(E&& e, const I (&shape)[N])
908 {
909 using shape_type = std::array<I, N>;
910 return reshape_view<L>(std::forward<E>(e), xtl::forward_sequence<shape_type, decltype(shape)>(shape));
911 }
912}
913
914#endif
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
size_type dimension() const noexcept
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 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
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.
xstrided_view(CTA &&e, SA &&shape, strides_type &&strides, std::size_t offset, layout_type layout) noexcept
Constructs an xstrided_view.
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.
Definition xstrides.hpp:566
auto strides(const E &e, stride_type type=stride_type::normal) noexcept
Get strides of an object.
Definition xstrides.hpp:248
standard mathematical functions for xexpressions
std::vector< xstrided_slice< std::ptrdiff_t > > xstrided_slice_vector
vector of slices used to build a xstrided_view
layout_type
Definition xlayout.hpp:24
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.