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 <type_traits>
16#include <utility>
17#include <variant>
18
19#include <xtl/xsequence.hpp>
20
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"
28
29namespace xt
30{
31 /***************************
32 * xstrided_view extension *
33 ***************************/
34
35 namespace extension
36 {
37 template <class Tag, class CT, class S, layout_type L, class FST>
39
40 template <class CT, class S, layout_type L, class FST>
42 {
43 using type = xtensor_empty_base;
44 };
45
46 template <class CT, class S, layout_type L, class FST>
47 struct xstrided_view_base : xstrided_view_base_impl<xexpression_tag_t<CT>, CT, S, L, FST>
48 {
49 };
50
51 template <class CT, class S, layout_type L, class FST>
52 using xstrided_view_base_t = typename xstrided_view_base<CT, S, L, FST>::type;
53 }
54
55 template <layout_type L1, layout_type L2, class T>
57 {
58 using type = std::conditional_t<L1 == L2 && L1 != layout_type::dynamic, xcontiguous_iterable<T>, xiterable<T>>;
59 };
60
61 template <layout_type L1, layout_type L2, class T>
62 using select_iterable_base_t = typename select_iterable_base<L1, L2, T>::type;
63
64
65 template <class CT, class S, layout_type L, class FST>
66 class xstrided_view;
67
68 template <class CT, class S, layout_type L, class FST>
70 {
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>;
83 static constexpr layout_type layout = L;
84 };
85
86 template <class CT, class S, layout_type L, class FST>
87 struct xiterable_inner_types<xstrided_view<CT, S, L, FST>>
88 {
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;
92
93 using const_stepper = std::conditional_t<
97
98 using stepper = std::conditional_t<
102 };
103
104 template <class CT, class S, layout_type L, class FST, class RHS>
105 struct can_assign<xstrided_view<CT, S, L, FST>, RHS> : can_assign<CT, RHS>
106 {
107 };
108
109 /*****************
110 * xstrided_view *
111 *****************/
112
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>>,
131 private xstrided_view_base<xstrided_view<CT, S, L, FST>>,
132 public extension::xstrided_view_base_t<CT, S, L, FST>
133 {
134 public:
135
136 using self_type = xstrided_view<CT, S, L, FST>;
137 using base_type = xstrided_view_base<self_type>;
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;
141
142 using xexpression_type = typename base_type::xexpression_type;
143 using base_type::is_const;
144
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;
152
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>;
159
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;
167
168 using stepper = typename iterable_base::stepper;
169 using const_stepper = typename iterable_base::const_stepper;
170
171 using base_type::contiguous_layout;
172 using base_type::static_layout;
173
174 using temporary_type = typename xcontainer_inner_types<self_type>::temporary_type;
175 using base_index_type = xindex_type_t<shape_type>;
176
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;
181
182 // load_simd/store_simd take the address of the flat storage, which requires the
183 // storage to expose lvalue references (not the case for lazy expressions wrapped
184 // in a flat_expression_adaptor).
185 static constexpr bool provides_simd_interface = has_simd_interface<xexpression_type>::value
187 && std::is_lvalue_reference_v<
188 decltype(std::declval<const storage_type&>()[0])>;
189
190 template <class CTA, class SA>
191 xstrided_view(CTA&& e, SA&& shape, strides_type&& strides, std::size_t offset, layout_type layout) noexcept;
192
193 xstrided_view(const xstrided_view& rhs) = default;
194
195 self_type& operator=(const self_type&);
196
197 template <class E>
198 self_type& operator=(const xexpression<E>& e);
199
200 template <class E>
201 disable_xexpression<E, self_type>& operator=(const E& e);
202
205 using base_type::is_contiguous;
206 using base_type::layout;
207 using base_type::shape;
208 using base_type::size;
209 using base_type::strides;
210
211 using base_type::operator();
212 using base_type::at;
214 using base_type::operator[];
215 using base_type::data;
217 using base_type::element;
219 using base_type::storage;
220
223
224 template <class T>
225 void fill(const T& value);
226
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;
233
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;
240
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);
245
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>
249 enable_indexed_stepper_t<STEP> stepper_end(const ST& shape, layout_type l);
250
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;
255
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;
260
261 template <class requested_type>
262 using simd_return_type = xt_simd::simd_return_type<value_type, requested_type>;
263
264 template <class align, class simd>
265 void store_simd(size_type i, const simd& e)
266 requires provides_simd_interface;
267
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;
271
272 reference data_element(size_type i);
273 const_reference data_element(size_type i) const;
274
275 reference flat(size_type i);
276 const_reference flat(size_type i) const;
277
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;
281
282 template <class E>
284
285 template <class E>
286 rebind_t<E> build_view(E&& e) const;
287
288 private:
289
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;
294
295 template <class It>
296 It data_xbegin_impl(It begin) const noexcept;
297
298 template <class It>
299 It data_xend_impl(It end, layout_type l, size_type offset) const noexcept;
300
301 void assign_temporary_impl(temporary_type&& tmp);
302
303 using base_type::set_offset;
304
305 template <class C>
306 friend class xstepper;
307 friend class xview_semantic<self_type>;
308 friend class xaccessible<self_type>;
309 friend class xconst_accessible<self_type>;
310 template <class D>
311 friend class xaxis_iterator;
312 template <class D>
313 friend class xaxis_slice_iterator;
314 };
315
316 /**************************
317 * xstrided_view builders *
318 **************************/
319
320 template <class T>
321 using xstrided_slice = std::variant<
322 T,
323
324 xrange_adaptor<placeholders::xtuph, T, T>,
325 xrange_adaptor<T, placeholders::xtuph, T>,
326 xrange_adaptor<T, T, placeholders::xtuph>,
327
328 xrange_adaptor<T, placeholders::xtuph, placeholders::xtuph>,
329 xrange_adaptor<placeholders::xtuph, T, placeholders::xtuph>,
330 xrange_adaptor<placeholders::xtuph, placeholders::xtuph, T>,
331
332 xrange_adaptor<T, T, T>,
333 xrange_adaptor<placeholders::xtuph, placeholders::xtuph, placeholders::xtuph>,
334
335 xrange<T>,
337
338 xall_tag,
341
346 using xstrided_slice_vector = std::vector<xstrided_slice<std::ptrdiff_t>>;
347
348 template <layout_type L = layout_type::dynamic, class E, class S, class X>
349 auto strided_view(E&& e, S&& shape, X&& stride, std::size_t offset = 0, layout_type layout = L) noexcept;
350
351 template <class E>
352 auto strided_view(E&& e, const xstrided_slice_vector& slices);
353
354 /********************************
355 * xstrided_view implementation *
356 ********************************/
357
362
371 template <class CT, class S, layout_type L, class FST>
372 template <class CTA, class SA>
373 inline xstrided_view<CT, S, L, FST>::xstrided_view(
374 CTA&& e,
375 SA&& shape,
376 strides_type&& strides,
377 std::size_t offset,
379 ) noexcept
380 : base_type(std::forward<CTA>(e), std::forward<SA>(shape), std::move(strides), offset, layout)
381 {
382 }
383
385
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&
388 {
389 temporary_type tmp(rhs);
390 return this->assign_temporary(std::move(tmp));
391 }
392
397
400 template <class CT, class S, layout_type L, class FST>
401 template <class E>
402 inline auto xstrided_view<CT, S, L, FST>::operator=(const xexpression<E>& e) -> self_type&
403 {
404 return semantic_base::operator=(e);
405 }
406
408
409 template <class CT, class S, layout_type L, class FST>
410 template <class E>
411 inline auto xstrided_view<CT, S, L, FST>::operator=(const E& e) -> disable_xexpression<E, self_type>&
412 {
413 this->fill(e);
414 return *this;
415 }
416
417 namespace xstrided_view_detail
418 {
419 template <class V, class T>
420 inline void run_assign_temporary_impl(V& v, const T& t, std::true_type /* enable strided assign */)
421 {
422 strided_loop_assigner<true>::run(v, t);
423 }
424
425 template <class V, class T>
426 inline void
427 run_assign_temporary_impl(V& v, const T& t, std::false_type /* fallback to iterator assign */)
428 {
429 std::copy(t.cbegin(), t.cend(), v.begin());
430 }
431 }
432
433 template <class CT, class S, layout_type L, class FST>
434 inline void xstrided_view<CT, S, L, FST>::assign_temporary_impl(temporary_type&& tmp)
435 {
436 constexpr bool
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>{});
439 }
440
445
450 template <class CT, class S, layout_type L, class FST>
451 template <class T>
452 inline void xstrided_view<CT, S, L, FST>::fill(const T& value)
453 {
455 {
456 std::fill(this->linear_begin(), this->linear_end(), value);
457 }
458 else
459 {
460 std::fill(this->begin(), this->end(), value);
461 }
462 }
463
465
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
468 {
469 return storage()[i];
470 }
471
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
474 {
475 return storage()[i];
476 }
477
478 template <class CT, class S, layout_type L, class FST>
479 inline auto xstrided_view<CT, S, L, FST>::flat(size_type i) -> reference
480 {
481 return storage()[i];
482 }
483
484 template <class CT, class S, layout_type L, class FST>
485 inline auto xstrided_view<CT, S, L, FST>::flat(size_type i) const -> const_reference
486 {
487 return storage()[i];
488 }
489
490 template <class CT, class S, layout_type L, class FST>
491 inline auto xstrided_view<CT, S, L, FST>::linear_begin() -> linear_iterator
492 {
493 return this->storage().begin() + static_cast<std::ptrdiff_t>(data_offset());
494 }
495
496 template <class CT, class S, layout_type L, class FST>
497 inline auto xstrided_view<CT, S, L, FST>::linear_end() -> linear_iterator
498 {
499 return this->storage().begin() + static_cast<std::ptrdiff_t>(data_offset() + size());
500 }
501
502 template <class CT, class S, layout_type L, class FST>
503 inline auto xstrided_view<CT, S, L, FST>::linear_begin() const -> const_linear_iterator
504 {
505 return this->linear_cbegin();
506 }
507
508 template <class CT, class S, layout_type L, class FST>
509 inline auto xstrided_view<CT, S, L, FST>::linear_end() const -> const_linear_iterator
510 {
511 return this->linear_cend();
512 }
513
514 template <class CT, class S, layout_type L, class FST>
515 inline auto xstrided_view<CT, S, L, FST>::linear_cbegin() const -> const_linear_iterator
516 {
517 return this->storage().cbegin() + static_cast<std::ptrdiff_t>(data_offset());
518 }
519
520 template <class CT, class S, layout_type L, class FST>
521 inline auto xstrided_view<CT, S, L, FST>::linear_cend() const -> const_linear_iterator
522 {
523 return this->storage().cbegin() + static_cast<std::ptrdiff_t>(data_offset() + size());
524 }
525
526 template <class CT, class S, layout_type L, class FST>
527 inline auto xstrided_view<CT, S, L, FST>::linear_rbegin() -> reverse_linear_iterator
528 {
529 return reverse_linear_iterator(this->linear_begin());
530 }
531
532 template <class CT, class S, layout_type L, class FST>
533 inline auto xstrided_view<CT, S, L, FST>::linear_rend() -> reverse_linear_iterator
534 {
535 return reverse_linear_iterator(this->linear_end());
536 }
537
538 template <class CT, class S, layout_type L, class FST>
539 inline auto xstrided_view<CT, S, L, FST>::linear_rbegin() const -> const_reverse_linear_iterator
540 {
541 return this->linear_crbegin();
542 }
543
544 template <class CT, class S, layout_type L, class FST>
545 inline auto xstrided_view<CT, S, L, FST>::linear_rend() const -> const_reverse_linear_iterator
546 {
547 return this->linear_crend();
548 }
549
550 template <class CT, class S, layout_type L, class FST>
551 inline auto xstrided_view<CT, S, L, FST>::linear_crbegin() const -> const_reverse_linear_iterator
552 {
553 return const_reverse_linear_iterator(this->linear_cbegin());
554 }
555
556 template <class CT, class S, layout_type L, class FST>
557 inline auto xstrided_view<CT, S, L, FST>::linear_crend() const -> const_reverse_linear_iterator
558 {
559 return const_reverse_linear_iterator(this->linear_cend());
560 }
561
562 /***************
563 * stepper api *
564 ***************/
565
566 template <class CT, class S, layout_type L, class FST>
567 template <class ST, class STEP>
568 inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) -> disable_indexed_stepper_t<STEP>
569 {
570 size_type offset = shape.size() - dimension();
571 return stepper(this, data_xbegin(), offset);
572 }
573
574 template <class CT, class S, layout_type L, class FST>
575 template <class ST, class STEP>
577 -> disable_indexed_stepper_t<STEP>
578 {
579 size_type offset = shape.size() - dimension();
580 return stepper(this, data_xend(l, offset), offset);
581 }
582
583 template <class CT, class S, layout_type L, class FST>
584 template <class ST, class STEP>
585 inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) -> enable_indexed_stepper_t<STEP>
586 {
587 size_type offset = shape.size() - dimension();
588 return stepper(this, offset);
589 }
590
591 template <class CT, class S, layout_type L, class FST>
592 template <class ST, class STEP>
594 -> enable_indexed_stepper_t<STEP>
595 {
596 size_type offset = shape.size() - dimension();
597 return stepper(this, offset, true);
598 }
599
600 template <class CT, class S, layout_type L, class FST>
601 template <class ST, class STEP>
602 inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) const
603 -> disable_indexed_stepper_t<STEP>
604 {
605 size_type offset = shape.size() - dimension();
606 return const_stepper(this, data_xbegin(), offset);
607 }
608
609 template <class CT, class S, layout_type L, class FST>
610 template <class ST, class STEP>
611 inline auto xstrided_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type l) const
612 -> disable_indexed_stepper_t<STEP>
613 {
614 size_type offset = shape.size() - dimension();
615 return const_stepper(this, data_xend(l, offset), offset);
616 }
617
618 template <class CT, class S, layout_type L, class FST>
619 template <class ST, class STEP>
620 inline auto xstrided_view<CT, S, L, FST>::stepper_begin(const ST& shape) const
621 -> enable_indexed_stepper_t<STEP>
622 {
623 size_type offset = shape.size() - dimension();
624 return const_stepper(this, offset);
625 }
626
627 template <class CT, class S, layout_type L, class FST>
628 template <class ST, class STEP>
629 inline auto xstrided_view<CT, S, L, FST>::stepper_end(const ST& shape, layout_type /*l*/) const
630 -> enable_indexed_stepper_t<STEP>
631 {
632 size_type offset = shape.size() - dimension();
633 return const_stepper(this, offset, true);
634 }
635
636 template <class CT, class S, layout_type L, class FST>
637 template <class It>
638 inline It xstrided_view<CT, S, L, FST>::data_xbegin_impl(It begin) const noexcept
639 {
640 return begin + static_cast<std::ptrdiff_t>(this->data_offset());
641 }
642
643 template <class CT, class S, layout_type L, class FST>
644 template <class It>
645 inline It
646 xstrided_view<CT, S, L, FST>::data_xend_impl(It begin, layout_type l, size_type offset) const noexcept
647 {
648 return strided_data_end(*this, begin + std::ptrdiff_t(this->data_offset()), l, offset);
649 }
650
651 template <class CT, class S, layout_type L, class FST>
652 inline auto xstrided_view<CT, S, L, FST>::data_xbegin() noexcept -> container_iterator
653 {
654 return data_xbegin_impl(this->storage().begin());
655 }
656
657 template <class CT, class S, layout_type L, class FST>
658 inline auto xstrided_view<CT, S, L, FST>::data_xbegin() const noexcept -> const_container_iterator
659 {
660 return data_xbegin_impl(this->storage().cbegin());
661 }
662
663 template <class CT, class S, layout_type L, class FST>
664 inline auto xstrided_view<CT, S, L, FST>::data_xend(layout_type l, size_type offset) noexcept
665 -> container_iterator
666 {
667 return data_xend_impl(this->storage().begin(), l, offset);
668 }
669
670 template <class CT, class S, layout_type L, class FST>
671 inline auto xstrided_view<CT, S, L, FST>::data_xend(layout_type l, size_type offset) const noexcept
672 -> const_container_iterator
673 {
674 return data_xend_impl(this->storage().cbegin(), l, offset);
675 }
676
677 template <class CT, class S, layout_type L, class FST>
678 template <class alignment, class simd>
679 inline void xstrided_view<CT, S, L, FST>::store_simd(size_type i, const simd& e)
680 requires provides_simd_interface
681 {
682 using align_mode = driven_align_mode_t<alignment, data_alignment>;
683 xt_simd::store_as(&(storage()[i]), e, align_mode());
684 }
685
686 template <class CT, class S, layout_type L, class FST>
687 template <class alignment, class requested_type, std::size_t N>
688 inline auto xstrided_view<CT, S, L, FST>::load_simd(size_type i) const -> simd_return_type<requested_type>
689 requires provides_simd_interface
690 {
691 using align_mode = driven_align_mode_t<alignment, data_alignment>;
692 return xt_simd::load_as<requested_type>(&(storage()[i]), align_mode());
693 }
694
695 template <class CT, class S, layout_type L, class FST>
696 template <class E>
697 inline auto xstrided_view<CT, S, L, FST>::build_view(E&& e) const -> rebind_t<E>
698 {
699 inner_shape_type sh(this->shape());
700 inner_strides_type str(this->strides());
701 return rebind_t<E>(
702 std::forward<E>(e),
703 std::move(sh),
704 std::move(str),
706 this->layout()
707 );
708 }
709
710 /*****************************************
711 * xstrided_view builders implementation *
712 *****************************************/
713
730 template <layout_type L, class E, class S, class X>
731 inline auto strided_view(E&& e, S&& shape, X&& strides, std::size_t offset, layout_type layout) noexcept
732 {
733 using view_type = xstrided_view<xclosure_t<E>, S, L>;
734 return view_type(std::forward<E>(e), std::forward<S>(shape), std::forward<X>(strides), offset, layout);
735 }
736
737 namespace detail
738 {
739 struct no_adj_strides_policy
740 {
741 protected:
742
743 inline void resize(std::size_t)
744 {
745 }
746
747 inline void set_fake_slice(std::size_t)
748 {
749 }
750
751 template <class ST, class S>
752 bool fill_args(
753 const xstrided_slice_vector& /*slices*/,
754 std::size_t /*sl_idx*/,
755 std::size_t /*i*/,
756 std::size_t /*old_shape*/,
757 const ST& /*old_stride*/,
758 S& /*shape*/,
759 get_strides_t<S>& /*strides*/
760 )
761 {
762 return false;
763 }
764 };
765 }
766
792 template <class E>
793 inline auto strided_view(E&& e, const xstrided_slice_vector& slices)
794 {
795 detail::strided_view_args<detail::no_adj_strides_policy> args;
796 args.fill_args(
797 e.shape(),
798 detail::get_strides<XTENSOR_DEFAULT_TRAVERSAL>(e),
799 detail::get_offset<XTENSOR_DEFAULT_TRAVERSAL>(e),
800 e.layout(),
801 slices
802 );
803 using view_type = xstrided_view<xclosure_t<E>, decltype(args.new_shape)>;
804 return view_type(
805 std::forward<E>(e),
806 std::move(args.new_shape),
807 std::move(args.new_strides),
808 args.new_offset,
809 args.new_layout
810 );
811 }
812
813 namespace detail
814 {
815 template <typename S>
816 struct rebind_shape;
817
818 template <std::size_t... X>
819 struct rebind_shape<xt::fixed_shape<X...>>
820 {
821 using type = xt::fixed_shape<X...>;
822 };
823
824 template <class S>
825 struct rebind_shape
826 {
827 using type = rebind_container_t<size_t, S>;
828 };
829
830 template <class S>
831 inline void recalculate_shape_impl(S& shape, size_t size)
832 {
833 if constexpr (std::is_signed_v<get_value_type_t<typename std::decay<S>::type>>)
834 {
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))
839 {
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);
843 }
844 }
845 }
846
847 template <class S>
848 inline auto recalculate_shape(S&& shape, size_t size)
849 {
850 return recalculate_shape_impl(shape, size);
851 }
852 }
853
854 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class S>
855 inline auto reshape_view(E&& e, S&& shape)
856 {
857 static_assert(
859 "traversal has to be row or column major"
860 );
861
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;
865
866 detail::recalculate_shape(shape, e.size());
867 xt::resize_container(strides, shape.size());
869 constexpr auto computed_layout = std::decay_t<E>::static_layout == L ? L : layout_type::dynamic;
870 using view_type = xstrided_view<
871 xclosure_t<E>,
872 unsigned_shape_type,
873 computed_layout,
874 detail::flat_adaptor_getter<xclosure_t<E>, L>>;
875 return view_type(
876 std::forward<E>(e),
877 xtl::forward_sequence<unsigned_shape_type, S>(shape),
878 std::move(strides),
879 0,
880 e.layout()
881 );
882 }
883
897 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class S>
898 inline auto reshape_view(E&& e, S&& shape, layout_type /*order*/)
899 {
900 return reshape_view<L>(std::forward<E>(e), std::forward<S>(shape));
901 }
902
903 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class E, class I, std::size_t N>
904 inline auto reshape_view(E&& e, const I (&shape)[N], layout_type order)
905 {
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);
908 }
909
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])
912 {
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));
915 }
916}
917
918#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(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.
self_type & operator=(const xexpression< E > &e)
The extended assignment operator.
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:574
auto strides(const E &e, stride_type type=stride_type::normal) noexcept
Get strides of an object.
Definition xstrides.hpp:254
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.