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
19#include <xtl/xsequence.hpp>
20#include <xtl/xvariant.hpp>
21
22#include "xexpression.hpp"
23#include "xiterable.hpp"
24#include "xlayout.hpp"
25#include "xsemantic.hpp"
26#include "xstorage.hpp"
27#include "xstrided_view_base.hpp"
28#include "xutils.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>
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;
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<
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>
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
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
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;
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 template <class CTA, class SA>
184 xstrided_view(CTA&& e, SA&& shape, strides_type&& strides, std::size_t offset, layout_type layout) noexcept;
185
186 xstrided_view(const xstrided_view& rhs) = default;
187
188 self_type& operator=(const self_type&);
189
190 template <class E>
191 self_type& operator=(const xexpression<E>& e);
192
193 template <class E>
194 disable_xexpression<E, self_type>& operator=(const E& e);
195
198 using base_type::is_contiguous;
199 using base_type::layout;
200 using base_type::shape;
201 using base_type::size;
202 using base_type::strides;
203
204 using base_type::operator();
205 using base_type::at;
206 using base_type::unchecked;
207 using base_type::operator[];
208 using base_type::data;
210 using base_type::element;
212 using base_type::storage;
213
216
217 template <class T>
218 void fill(const T& value);
219
220 linear_iterator linear_begin();
221 linear_iterator linear_end();
222 const_linear_iterator linear_begin() const;
223 const_linear_iterator linear_end() const;
224 const_linear_iterator linear_cbegin() const;
225 const_linear_iterator linear_cend() const;
226
227 reverse_linear_iterator linear_rbegin();
228 reverse_linear_iterator linear_rend();
229 const_reverse_linear_iterator linear_rbegin() const;
230 const_reverse_linear_iterator linear_rend() const;
231 const_reverse_linear_iterator linear_crbegin() const;
232 const_reverse_linear_iterator linear_crend() const;
233
234 template <class ST, class STEP = stepper>
235 disable_indexed_stepper_t<STEP> stepper_begin(const ST& shape);
236 template <class ST, class STEP = stepper>
238
239 template <class ST, class STEP = stepper>
240 enable_indexed_stepper_t<STEP> stepper_begin(const ST& shape);
241 template <class ST, class STEP = stepper>
243
244 template <class ST, class STEP = const_stepper>
245 disable_indexed_stepper_t<STEP> stepper_begin(const ST& shape) const;
246 template <class ST, class STEP = const_stepper>
247 disable_indexed_stepper_t<STEP> stepper_end(const ST& shape, layout_type l) const;
248
249 template <class ST, class STEP = const_stepper>
250 enable_indexed_stepper_t<STEP> stepper_begin(const ST& shape) const;
251 template <class ST, class STEP = const_stepper>
252 enable_indexed_stepper_t<STEP> stepper_end(const ST& shape, layout_type l) const;
253
254 template <class requested_type>
255 using simd_return_type = xt_simd::simd_return_type<value_type, requested_type>;
256
257 template <class T, class R>
258 using enable_simd_interface = std::enable_if_t<has_simd_interface<T>::value && L != layout_type::dynamic, R>;
259
260 template <class align, class simd, class T = xexpression_type>
261 enable_simd_interface<T, void> store_simd(size_type i, const simd& e);
262 template <
263 class align,
264 class requested_type = value_type,
266 class T = xexpression_type>
268
269 reference data_element(size_type i);
270 const_reference data_element(size_type i) const;
271
272 reference flat(size_type i);
273 const_reference flat(size_type i) const;
274
275 using container_iterator = std::
276 conditional_t<is_const, typename storage_type::const_iterator, typename storage_type::iterator>;
277 using const_container_iterator = typename storage_type::const_iterator;
278
279 template <class E>
281
282 template <class E>
283 rebind_t<E> build_view(E&& e) const;
284
285 private:
286
287 container_iterator data_xbegin() noexcept;
288 const_container_iterator data_xbegin() const noexcept;
289 container_iterator data_xend(layout_type l, size_type offset) noexcept;
290 const_container_iterator data_xend(layout_type l, size_type offset) const noexcept;
291
293 It data_xbegin_impl(It begin) const noexcept;
294
296 It data_xend_impl(It end, layout_type l, size_type offset) const noexcept;
297
298 void assign_temporary_impl(temporary_type&& tmp);
299
300 using base_type::set_offset;
301
311 };
312
313 /**************************
314 * xstrided_view builders *
315 **************************/
316
317 template <class T>
318 using xstrided_slice = xtl::variant<
319 T,
320
321 xrange_adaptor<placeholders::xtuph, T, T>,
322 xrange_adaptor<T, placeholders::xtuph, T>,
323 xrange_adaptor<T, T, placeholders::xtuph>,
324
325 xrange_adaptor<T, placeholders::xtuph, placeholders::xtuph>,
326 xrange_adaptor<placeholders::xtuph, T, placeholders::xtuph>,
327 xrange_adaptor<placeholders::xtuph, placeholders::xtuph, T>,
328
329 xrange_adaptor<T, T, T>,
330 xrange_adaptor<placeholders::xtuph, placeholders::xtuph, placeholders::xtuph>,
331
332 xrange<T>,
334
335 xall_tag,
338
343 using xstrided_slice_vector = std::vector<xstrided_slice<std::ptrdiff_t>>;
344
346 auto strided_view(E&& e, S&& shape, X&& stride, std::size_t offset = 0, layout_type layout = L) noexcept;
347
348 template <class E>
350
351 /********************************
352 * xstrided_view implementation *
353 ********************************/
354
371 CTA&& e,
372 SA&& shape,
373 strides_type&& strides,
374 std::size_t offset,
376 ) noexcept
377 : base_type(std::forward<CTA>(e), std::forward<SA>(shape), std::move(strides), offset, layout)
378 {
379 }
380
382
383 template <class CT, class S, layout_type L, class FST>
384 inline auto xstrided_view<CT, S, L, FST>::operator=(const self_type& rhs) -> self_type&
385 {
387 return this->assign_temporary(std::move(tmp));
388 }
389
397 template <class CT, class S, layout_type L, class FST>
398 template <class E>
400 {
401 return semantic_base::operator=(e);
402 }
403
405
406 template <class CT, class S, layout_type L, class FST>
407 template <class E>
409 {
410 this->fill(e);
411 return *this;
412 }
413
414 namespace xstrided_view_detail
415 {
416 template <class V, class T>
417 inline void run_assign_temporary_impl(V& v, const T& t, std::true_type /* enable strided assign */)
418 {
419 strided_loop_assigner<true>::run(v, t);
420 }
421
422 template <class V, class T>
423 inline void
424 run_assign_temporary_impl(V& v, const T& t, std::false_type /* fallback to iterator assign */)
425 {
426 std::copy(t.cbegin(), t.cend(), v.begin());
427 }
428 }
429
430 template <class CT, class S, layout_type L, class FST>
431 inline void xstrided_view<CT, S, L, FST>::assign_temporary_impl(temporary_type&& tmp)
432 {
433 constexpr bool
434 fast_assign = xassign_traits<xstrided_view<CT, S, L, FST>, temporary_type>::simd_strided_assign();
435 xstrided_view_detail::run_assign_temporary_impl(*this, tmp, std::integral_constant<bool, fast_assign>{});
436 }
437
442
447 template <class CT, class S, layout_type L, class FST>
448 template <class T>
449 inline void xstrided_view<CT, S, L, FST>::fill(const T& value)
450 {
452 {
453 std::fill(this->linear_begin(), this->linear_end(), value);
454 }
455 else
456 {
457 std::fill(this->begin(), this->end(), value);
458 }
459 }
460
462
463 template <class CT, class S, layout_type L, class FST>
464 inline auto xstrided_view<CT, S, L, FST>::data_element(size_type i) -> reference
465 {
466 return storage()[i];
467 }
468
469 template <class CT, class S, layout_type L, class FST>
470 inline auto xstrided_view<CT, S, L, FST>::data_element(size_type i) const -> const_reference
471 {
472 return storage()[i];
473 }
474
475 template <class CT, class S, layout_type L, class FST>
476 inline auto xstrided_view<CT, S, L, FST>::flat(size_type i) -> reference
477 {
478 return storage()[i];
479 }
480
481 template <class CT, class S, layout_type L, class FST>
482 inline auto xstrided_view<CT, S, L, FST>::flat(size_type i) const -> const_reference
483 {
484 return storage()[i];
485 }
486
487 template <class CT, class S, layout_type L, class FST>
488 inline auto xstrided_view<CT, S, L, FST>::linear_begin() -> linear_iterator
489 {
490 return this->storage().begin() + static_cast<std::ptrdiff_t>(data_offset());
491 }
492
493 template <class CT, class S, layout_type L, class FST>
494 inline auto xstrided_view<CT, S, L, FST>::linear_end() -> linear_iterator
495 {
496 return this->storage().begin() + static_cast<std::ptrdiff_t>(data_offset() + size());
497 }
498
499 template <class CT, class S, layout_type L, class FST>
500 inline auto xstrided_view<CT, S, L, FST>::linear_begin() const -> const_linear_iterator
501 {
502 return this->linear_cbegin();
503 }
504
505 template <class CT, class S, layout_type L, class FST>
506 inline auto xstrided_view<CT, S, L, FST>::linear_end() const -> const_linear_iterator
507 {
508 return this->linear_cend();
509 }
510
511 template <class CT, class S, layout_type L, class FST>
512 inline auto xstrided_view<CT, S, L, FST>::linear_cbegin() const -> const_linear_iterator
513 {
514 return this->storage().cbegin() + static_cast<std::ptrdiff_t>(data_offset());
515 }
516
517 template <class CT, class S, layout_type L, class FST>
518 inline auto xstrided_view<CT, S, L, FST>::linear_cend() const -> const_linear_iterator
519 {
520 return this->storage().cbegin() + static_cast<std::ptrdiff_t>(data_offset() + size());
521 }
522
523 template <class CT, class S, layout_type L, class FST>
524 inline auto xstrided_view<CT, S, L, FST>::linear_rbegin() -> reverse_linear_iterator
525 {
526 return reverse_linear_iterator(this->linear_begin());
527 }
528
529 template <class CT, class S, layout_type L, class FST>
530 inline auto xstrided_view<CT, S, L, FST>::linear_rend() -> reverse_linear_iterator
531 {
532 return reverse_linear_iterator(this->linear_end());
533 }
534
535 template <class CT, class S, layout_type L, class FST>
536 inline auto xstrided_view<CT, S, L, FST>::linear_rbegin() const -> const_reverse_linear_iterator
537 {
538 return this->linear_crbegin();
539 }
540
541 template <class CT, class S, layout_type L, class FST>
542 inline auto xstrided_view<CT, S, L, FST>::linear_rend() const -> const_reverse_linear_iterator
543 {
544 return this->linear_crend();
545 }
546
547 template <class CT, class S, layout_type L, class FST>
548 inline auto xstrided_view<CT, S, L, FST>::linear_crbegin() const -> const_reverse_linear_iterator
549 {
550 return const_reverse_linear_iterator(this->linear_cbegin());
551 }
552
553 template <class CT, class S, layout_type L, class FST>
554 inline auto xstrided_view<CT, S, L, FST>::linear_crend() const -> const_reverse_linear_iterator
555 {
556 return const_reverse_linear_iterator(this->linear_cend());
557 }
558
559 /***************
560 * stepper api *
561 ***************/
562
563 template <class CT, class S, layout_type L, class FST>
564 template <class ST, class STEP>
565 inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) -> disable_indexed_stepper_t<STEP>
566 {
567 size_type offset = shape.size() - dimension();
568 return stepper(this, data_xbegin(), offset);
569 }
570
571 template <class CT, class S, layout_type L, class FST>
572 template <class ST, class STEP>
573 inline auto xstrided_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type l)
574 -> disable_indexed_stepper_t<STEP>
575 {
576 size_type offset = shape.size() - dimension();
577 return stepper(this, data_xend(l, offset), offset);
578 }
579
580 template <class CT, class S, layout_type L, class FST>
581 template <class ST, class STEP>
582 inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) -> enable_indexed_stepper_t<STEP>
583 {
584 size_type offset = shape.size() - dimension();
585 return stepper(this, offset);
586 }
587
588 template <class CT, class S, layout_type L, class FST>
589 template <class ST, class STEP>
590 inline auto xstrided_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type /*l*/)
591 -> enable_indexed_stepper_t<STEP>
592 {
593 size_type offset = shape.size() - dimension();
594 return stepper(this, offset, true);
595 }
596
597 template <class CT, class S, layout_type L, class FST>
598 template <class ST, class STEP>
599 inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) const
600 -> disable_indexed_stepper_t<STEP>
601 {
602 size_type offset = shape.size() - dimension();
603 return const_stepper(this, data_xbegin(), offset);
604 }
605
606 template <class CT, class S, layout_type L, class FST>
607 template <class ST, class STEP>
608 inline auto xstrided_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type l) const
609 -> disable_indexed_stepper_t<STEP>
610 {
611 size_type offset = shape.size() - dimension();
612 return const_stepper(this, data_xend(l, offset), offset);
613 }
614
615 template <class CT, class S, layout_type L, class FST>
616 template <class ST, class STEP>
617 inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) const
618 -> enable_indexed_stepper_t<STEP>
619 {
620 size_type offset = shape.size() - dimension();
621 return const_stepper(this, offset);
622 }
623
624 template <class CT, class S, layout_type L, class FST>
625 template <class ST, class STEP>
626 inline auto xstrided_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type /*l*/) const
627 -> enable_indexed_stepper_t<STEP>
628 {
629 size_type offset = shape.size() - dimension();
630 return const_stepper(this, offset, true);
631 }
632
633 template <class CT, class S, layout_type L, class FST>
634 template <class It>
635 inline It xstrided_view<CT, S, L, FST>::data_xbegin_impl(It begin) const noexcept
636 {
637 return begin + static_cast<std::ptrdiff_t>(this->data_offset());
638 }
639
640 template <class CT, class S, layout_type L, class FST>
641 template <class It>
642 inline It
643 xstrided_view<CT, S, L, FST>::data_xend_impl(It begin, layout_type l, size_type offset) const noexcept
644 {
645 return strided_data_end(*this, begin + std::ptrdiff_t(this->data_offset()), l, offset);
646 }
647
648 template <class CT, class S, layout_type L, class FST>
649 inline auto xstrided_view<CT, S, L, FST>::data_xbegin() noexcept -> container_iterator
650 {
651 return data_xbegin_impl(this->storage().begin());
652 }
653
654 template <class CT, class S, layout_type L, class FST>
655 inline auto xstrided_view<CT, S, L, FST>::data_xbegin() const noexcept -> const_container_iterator
656 {
657 return data_xbegin_impl(this->storage().cbegin());
658 }
659
660 template <class CT, class S, layout_type L, class FST>
661 inline auto xstrided_view<CT, S, L, FST>::data_xend(layout_type l, size_type offset) noexcept
662 -> container_iterator
663 {
664 return data_xend_impl(this->storage().begin(), l, offset);
665 }
666
667 template <class CT, class S, layout_type L, class FST>
668 inline auto xstrided_view<CT, S, L, FST>::data_xend(layout_type l, size_type offset) const noexcept
669 -> const_container_iterator
670 {
671 return data_xend_impl(this->storage().cbegin(), l, offset);
672 }
673
674 template <class CT, class S, layout_type L, class FST>
675 template <class alignment, class simd, class T>
676 inline auto xstrided_view<CT, S, L, FST>::store_simd(size_type i, const simd& e)
677 -> enable_simd_interface<T, void>
678 {
679 using align_mode = driven_align_mode_t<alignment, data_alignment>;
680 xt_simd::store_as(&(storage()[i]), e, align_mode());
681 }
682
683 template <class CT, class S, layout_type L, class FST>
684 template <class alignment, class requested_type, std::size_t N, class T>
685 inline auto xstrided_view<CT, S, L, FST>::load_simd(size_type i) const
686 -> enable_simd_interface<T, simd_return_type<requested_type>>
687 {
688 using align_mode = driven_align_mode_t<alignment, data_alignment>;
689 return xt_simd::load_as<requested_type>(&(storage()[i]), align_mode());
690 }
691
692 template <class CT, class S, layout_type L, class FST>
693 template <class E>
694 inline auto xstrided_view<CT, S, L, FST>::build_view(E&& e) const -> rebind_t<E>
695 {
696 inner_shape_type sh(this->shape());
697 inner_strides_type str(this->strides());
698 return rebind_t<E>(
699 std::forward<E>(e),
700 std::move(sh),
701 std::move(str),
703 this->layout()
704 );
705 }
706
707 /*****************************************
708 * xstrided_view builders implementation *
709 *****************************************/
710
727 template <layout_type L, class E, class S, class X>
728 inline auto strided_view(E&& e, S&& shape, X&& strides, std::size_t offset, layout_type layout) noexcept
729 {
730 using view_type = xstrided_view<xclosure_t<E>, S, L>;
731 return view_type(std::forward<E>(e), std::forward<S>(shape), std::forward<X>(strides), offset, layout);
732 }
733
734 namespace detail
735 {
736 struct no_adj_strides_policy
737 {
738 protected:
739
740 inline void resize(std::size_t)
741 {
742 }
743
744 inline void set_fake_slice(std::size_t)
745 {
746 }
747
748 template <class ST, class S>
749 bool fill_args(
750 const xstrided_slice_vector& /*slices*/,
751 std::size_t /*sl_idx*/,
752 std::size_t /*i*/,
753 std::size_t /*old_shape*/,
754 const ST& /*old_stride*/,
755 S& /*shape*/,
756 get_strides_t<S>& /*strides*/
757 )
758 {
759 return false;
760 }
761 };
762 }
763
789 template <class E>
790 inline auto strided_view(E&& e, const xstrided_slice_vector& slices)
791 {
792 detail::strided_view_args<detail::no_adj_strides_policy> args;
793 args.fill_args(
794 e.shape(),
795 detail::get_strides<XTENSOR_DEFAULT_TRAVERSAL>(e),
796 detail::get_offset<XTENSOR_DEFAULT_TRAVERSAL>(e),
797 e.layout(),
798 slices
799 );
800 using view_type = xstrided_view<xclosure_t<E>, decltype(args.new_shape)>;
801 return view_type(
802 std::forward<E>(e),
803 std::move(args.new_shape),
804 std::move(args.new_strides),
805 args.new_offset,
806 args.new_layout
807 );
808 }
809
810 namespace detail
811 {
812 template <typename S>
813 struct rebind_shape;
814
815 template <std::size_t... X>
816 struct rebind_shape<xt::fixed_shape<X...>>
817 {
818 using type = xt::fixed_shape<X...>;
819 };
820
821 template <class S>
822 struct rebind_shape
823 {
824 using type = rebind_container_t<size_t, S>;
825 };
826
827 template <
828 class S,
829 std::enable_if_t<std::is_signed<get_value_type_t<typename std::decay<S>::type>>::value, bool> = true>
830 inline void recalculate_shape_impl(S& shape, size_t size)
831 {
832 using value_type = get_value_type_t<typename std::decay_t<S>>;
833 XTENSOR_ASSERT(std::count(shape.cbegin(), shape.cend(), -1) <= 1);
834 auto iter = std::find(shape.begin(), shape.end(), -1);
835 if (iter != std::end(shape))
836 {
837 const auto total = std::accumulate(shape.cbegin(), shape.cend(), -1, std::multiplies<int>{});
838 const auto missing_dimension = size / total;
839 (*iter) = static_cast<value_type>(missing_dimension);
840 }
841 }
842
843 template <
844 class S,
845 std::enable_if_t<!std::is_signed<get_value_type_t<typename std::decay<S>::type>>::value, bool> = true>
846 inline void recalculate_shape_impl(S&, size_t)
847 {
848 }
849
850 template <class S>
851 inline auto recalculate_shape(S&& shape, size_t size)
852 {
853 return recalculate_shape_impl(shape, size);
854 }
855 }
856
857 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class S>
858 inline auto reshape_view(E&& e, S&& shape)
859 {
860 static_assert(
862 "traversal has to be row or column major"
863 );
864
865 using shape_type = std::decay_t<decltype(shape)>;
866 using unsigned_shape_type = typename detail::rebind_shape<shape_type>::type;
867 get_strides_t<unsigned_shape_type> strides;
868
869 detail::recalculate_shape(shape, e.size());
870 xt::resize_container(strides, shape.size());
872 constexpr auto computed_layout = std::decay_t<E>::static_layout == L ? L : layout_type::dynamic;
873 using view_type = xstrided_view<
874 xclosure_t<E>,
875 unsigned_shape_type,
876 computed_layout,
877 detail::flat_adaptor_getter<xclosure_t<E>, L>>;
878 return view_type(
879 std::forward<E>(e),
880 xtl::forward_sequence<unsigned_shape_type, S>(shape),
881 std::move(strides),
882 0,
883 e.layout()
884 );
885 }
886
900 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class S>
901 inline auto reshape_view(E&& e, S&& shape, layout_type /*order*/)
902 {
903 return reshape_view<L>(std::forward<E>(e), std::forward<S>(shape));
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], layout_type order)
908 {
909 using shape_type = std::array<std::size_t, N>;
910 return reshape_view<L>(std::forward<E>(e), xtl::forward_sequence<shape_type, decltype(shape)>(shape), order);
911 }
912
913 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class I, std::size_t N>
914 inline auto reshape_view(E&& e, const I (&shape)[N])
915 {
916 using shape_type = std::array<I, N>;
917 return reshape_view<L>(std::forward<E>(e), xtl::forward_sequence<shape_type, decltype(shape)>(shape));
918 }
919}
920
921#endif
Fixed shape implementation for compile time defined arrays.
Base class for implementation of common expression access methods.
Class for iteration over (N-1)-dimensional slices, where N is the dimension of the underlying express...
Class for iteration over one-dimensional slices.
Base class for implementation of common expression constant access methods.
size_type size() const noexcept
Returns the size of the expression.
size_type dimension() const noexcept
Returns the number of dimensions of the expression.
layout_type layout() const noexcept
Returns the layout of the xtrided_view_base.
bool has_linear_assign(const O &strides) const noexcept
Checks whether the xstrided_view_base can be linearly assigned to an expression with the specified st...
const inner_strides_type & strides() const noexcept
Returns the strides 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_backstrides_type & backstrides() const noexcept
Returns the backstrides of the xtrided_view_base.
const inner_shape_type & shape() const noexcept
Returns the shape of the xtrided_view_base.
size_type data_offset() const noexcept
Returns the offset to the first element in the view.
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.
View of an xexpression using strides.
layout_type layout() const noexcept
Returns the layout of the xtrided_view_base.
void fill(const T &value)
Fills the view with the given value.
const inner_strides_type & strides() const noexcept
Returns the strides of the xtrided_view_base.
const inner_shape_type & shape() const noexcept
Returns the shape of the xtrided_view_base.
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.
storage_type & storage() noexcept
Returns a reference to the buffer containing the elements of the view.
Implementation of the xsemantic_base interface for multidimensional views.
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
standard mathematical functions for xexpressions
layout_type
Definition xlayout.hpp:24
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.