xtensor
Loading...
Searching...
No Matches
xview.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_VIEW_HPP
11#define XTENSOR_VIEW_HPP
12
13#include <algorithm>
14#include <array>
15#include <cstddef>
16#include <tuple>
17#include <type_traits>
18#include <utility>
19
20#include <xtl/xclosure.hpp>
21#include <xtl/xmeta_utils.hpp>
22#include <xtl/xsequence.hpp>
23#include <xtl/xtype_traits.hpp>
24
25#include "xaccessible.hpp"
26#include "xarray.hpp"
27#include "xbroadcast.hpp"
28#include "xcontainer.hpp"
29#include "xiterable.hpp"
30#include "xsemantic.hpp"
31#include "xslice.hpp"
32#include "xtensor.hpp"
33#include "xtensor_config.hpp"
34#include "xtensor_forward.hpp"
35#include "xview_utils.hpp"
36
37namespace xt
38{
39
40 /*******************
41 * xview extension *
42 *******************/
43
44 namespace extension
45 {
46 template <class Tag, class CT, class... S>
48
49 template <class CT, class... S>
54
55 template <class CT, class... S>
56 struct xview_base : xview_base_impl<xexpression_tag_t<CT>, CT, S...>
57 {
58 };
59
60 template <class CT, class... S>
61 using xview_base_t = typename xview_base<CT, S...>::type;
62 }
63
64 /*********************
65 * xview declaration *
66 *********************/
67
68 template <bool is_const, class CT, class... S>
69 class xview_stepper;
70
71 template <class ST, class... S>
72 struct xview_shape_type;
73
74 namespace detail
75 {
76
77 template <class T>
78 struct is_xrange : std::false_type
79 {
80 };
81
82 template <class T>
83 struct is_xrange<xrange<T>> : std::true_type
84 {
85 };
86
87 template <class S>
88 struct is_xall_slice : std::false_type
89 {
90 };
91
92 template <class T>
93 struct is_xall_slice<xall<T>> : std::true_type
94 {
95 };
96
97 template <layout_type L, bool valid, bool all_seen, bool range_seen, class V>
98 struct is_contiguous_view_impl
99 {
100 static constexpr bool value = false;
101 };
102
103 template <class T>
104 struct static_dimension
105 {
106 static constexpr std::ptrdiff_t value = -1;
107 };
108
109 template <class T, std::size_t N>
110 struct static_dimension<std::array<T, N>>
111 {
112 static constexpr std::ptrdiff_t value = static_cast<std::ptrdiff_t>(N);
113 };
114
115 template <class T, std::size_t N>
116 struct static_dimension<xt::const_array<T, N>>
117 {
118 static constexpr std::ptrdiff_t value = static_cast<std::ptrdiff_t>(N);
119 };
120
121 template <std::size_t... I>
122 struct static_dimension<xt::fixed_shape<I...>>
123 {
124 static constexpr std::ptrdiff_t value = sizeof...(I);
125 };
126
127 // if we have the same number of integers as we have static dimensions
128 // this can be interpreted like a xscalar
129 template <class CT, class... S>
130 struct is_xscalar_impl<xview<CT, S...>>
131 {
132 static constexpr bool value = static_cast<std::ptrdiff_t>(integral_count<S...>()
133 ) == static_dimension<typename std::decay_t<CT>::shape_type>::value
134 ? true
135 : false;
136 };
137
138 template <class S>
139 struct is_strided_slice_impl : std::true_type
140 {
141 };
142
143 template <class T>
144 struct is_strided_slice_impl<xkeep_slice<T>> : std::false_type
145 {
146 };
147
148 template <class T>
149 struct is_strided_slice_impl<xdrop_slice<T>> : std::false_type
150 {
151 };
152
153 // If we have no discontiguous slices, we can calculate strides for this view.
154 template <class E, class... S>
155 struct is_strided_view
156 : std::integral_constant<
157 bool,
158 xtl::conjunction<has_data_interface<E>, is_strided_slice_impl<std::decay_t<S>>...>::value>
159 {
160 };
161
162 // if row major the view can only be (statically) computed as contiguous if:
163 // any number of integers is followed by either one or no range which
164 // are followed by explicit (or implicit) all's
165 //
166 // e.g.
167 // (i, j, all(), all()) == contiguous
168 // (i, range(0, 2), all()) == contiguous
169 // (i) == contiguous (implicit all slices)
170 // (i, all(), j) == *not* contiguous
171 // (i, range(0, 2), range(0, 2)) == *not* contiguous etc.
172 template <bool valid, bool all_seen, bool range_seen, class V>
173 struct is_contiguous_view_impl<layout_type::row_major, valid, all_seen, range_seen, V>
174 {
175 using slice = xtl::mpl::front_t<V>;
176 static constexpr bool is_range_slice = is_xrange<slice>::value;
177 static constexpr bool is_int_slice = xtl::is_integral<slice>::value;
178 static constexpr bool is_all_slice = is_xall_slice<slice>::value;
179 static constexpr bool have_all_seen = all_seen || is_all_slice;
180 static constexpr bool have_range_seen = is_range_slice;
181
182 static constexpr bool is_valid = valid
183 && (have_all_seen
184 ? is_all_slice
185 : (!range_seen && (is_int_slice || is_range_slice)));
186
187 static constexpr bool value = is_contiguous_view_impl < layout_type::row_major, is_valid,
188 have_all_seen, range_seen || is_range_slice,
189 xtl::mpl::pop_front_t < V >> ::value;
190 };
191
192 template <bool valid, bool all_seen, bool range_seen>
193 struct is_contiguous_view_impl<layout_type::row_major, valid, all_seen, range_seen, xtl::mpl::vector<>>
194 {
195 static constexpr bool value = valid;
196 };
197
198 // For column major the *same* but reverse is true -- with the additional
199 // constraint that we have to know the dimension at compile time otherwise
200 // we cannot make the decision as there might be implicit all's following.
201 template <bool valid, bool int_seen, bool range_seen, class V>
202 struct is_contiguous_view_impl<layout_type::column_major, valid, int_seen, range_seen, V>
203 {
204 using slice = xtl::mpl::front_t<V>;
205 static constexpr bool is_range_slice = is_xrange<slice>::value;
206 static constexpr bool is_int_slice = xtl::is_integral<slice>::value;
207 static constexpr bool is_all_slice = is_xall_slice<slice>::value;
208
209 static constexpr bool have_int_seen = int_seen || is_int_slice;
210
211 static constexpr bool is_valid = valid
212 && (have_int_seen
213 ? is_int_slice
214 : (!range_seen && (is_all_slice || is_range_slice)));
215 static constexpr bool value = is_contiguous_view_impl < layout_type::column_major, is_valid,
216 have_int_seen, is_range_slice || range_seen,
217 xtl::mpl::pop_front_t < V >> ::value;
218 };
219
220 template <bool valid, bool int_seen, bool range_seen>
221 struct is_contiguous_view_impl<layout_type::column_major, valid, int_seen, range_seen, xtl::mpl::vector<>>
222 {
223 static constexpr bool value = valid;
224 };
225
226 // TODO relax has_data_interface constraint here!
227 template <class E, class... S>
228 struct is_contiguous_view
229 : std::integral_constant<
230 bool,
231 has_data_interface<E>::value
232 && !(
233 E::static_layout == layout_type::column_major
234 && static_cast<std::size_t>(static_dimension<typename E::shape_type>::value) != sizeof...(S)
235 )
236 && is_contiguous_view_impl<E::static_layout, true, false, false, xtl::mpl::vector<S...>>::value>
237 {
238 };
239
240 template <layout_type L, class T, std::ptrdiff_t offset>
241 struct unwrap_offset_container
242 {
243 using type = void;
244 };
245
246 template <class T, std::ptrdiff_t offset>
247 struct unwrap_offset_container<layout_type::row_major, T, offset>
248 {
249 using type = sequence_view<T, offset, static_dimension<T>::value>;
250 };
251
252 template <class T, std::ptrdiff_t start, std::ptrdiff_t end, std::ptrdiff_t offset>
253 struct unwrap_offset_container<layout_type::row_major, sequence_view<T, start, end>, offset>
254 {
255 using type = sequence_view<T, start + offset, end>;
256 };
257
258 template <class T, std::ptrdiff_t offset>
259 struct unwrap_offset_container<layout_type::column_major, T, offset>
260 {
261 using type = sequence_view<T, 0, static_dimension<T>::value - offset>;
262 };
263
264 template <class T, std::ptrdiff_t start, std::ptrdiff_t end, std::ptrdiff_t offset>
265 struct unwrap_offset_container<layout_type::column_major, sequence_view<T, start, end>, offset>
266 {
267 using type = sequence_view<T, start, end - offset>;
268 };
269
270 template <class E, class... S>
271 struct get_contigous_shape_type
272 {
273 // if we have no `range` in the slices we can re-use the shape with an offset
274 using type = std::conditional_t<
275 xtl::disjunction<is_xrange<S>...>::value,
276 typename xview_shape_type<typename E::shape_type, S...>::type,
277 // In the false branch we know that we have only integers at the front OR end, and NO range
278 typename unwrap_offset_container<E::static_layout, typename E::inner_shape_type, integral_count<S...>()>::type>;
279 };
280
281 template <class T>
282 struct is_sequence_view : std::integral_constant<bool, false>
283 {
284 };
285
286 template <class T, std::ptrdiff_t S, std::ptrdiff_t E>
287 struct is_sequence_view<sequence_view<T, S, E>> : std::integral_constant<bool, true>
288 {
289 };
290 }
291
292 template <class CT, class... S>
294 {
295 using xexpression_type = std::decay_t<CT>;
297 using const_reference = typename xexpression_type::const_reference;
298 using size_type = typename xexpression_type::size_type;
299 using temporary_type = view_temporary_type_t<xexpression_type, S...>;
300
301 static constexpr layout_type layout = detail::is_contiguous_view<xexpression_type, S...>::value
302 ? xexpression_type::static_layout
304
305 static constexpr bool is_const = std::is_const<std::remove_reference_t<CT>>::value;
306
307 using extract_storage_type = xtl::mpl::eval_if_t<
309 detail::expr_storage_type<xexpression_type>,
311 using storage_type = std::conditional_t<is_const, const extract_storage_type, extract_storage_type>;
312 };
313
314 template <class CT, class... S>
316 {
317 using xexpression_type = std::decay_t<CT>;
318
319 static constexpr bool is_strided_view = detail::is_strided_view<xexpression_type, S...>::value;
320 static constexpr bool is_contiguous_view = detail::is_contiguous_view<xexpression_type, S...>::value;
321
322 using inner_shape_type = std::conditional_t<
323 is_contiguous_view,
324 typename detail::get_contigous_shape_type<xexpression_type, S...>::type,
325 typename xview_shape_type<typename xexpression_type::shape_type, S...>::type>;
326
327 using stepper = std::conditional_t<
328 is_strided_view,
329 xstepper<xview<CT, S...>>,
331
332 using const_stepper = std::conditional_t<
333 is_strided_view,
334 xstepper<const xview<CT, S...>>,
336 };
337
352 template <class CT, class... S>
353 class xview : public xview_semantic<xview<CT, S...>>,
354 public std::conditional_t<
355 detail::is_contiguous_view<std::decay_t<CT>, S...>::value,
356 xcontiguous_iterable<xview<CT, S...>>,
357 xiterable<xview<CT, S...>>>,
358 public xaccessible<xview<CT, S...>>,
359 public extension::xview_base_t<CT, S...>
360 {
361 public:
362
363 using self_type = xview<CT, S...>;
365 using xexpression_type = std::decay_t<CT>;
367 using temporary_type = typename xcontainer_inner_types<self_type>::temporary_type;
368
370 using extension_base = extension::xview_base_t<CT, S...>;
371 using expression_tag = typename extension_base::expression_tag;
372
373 static constexpr bool is_const = std::is_const<std::remove_reference_t<CT>>::value;
374 using value_type = typename xexpression_type::value_type;
375 using simd_value_type = xt_simd::simd_type<value_type>;
376 using bool_load_type = typename xexpression_type::bool_load_type;
377 using reference = typename inner_types::reference;
378 using const_reference = typename inner_types::const_reference;
379 using pointer = std::
380 conditional_t<is_const, typename xexpression_type::const_pointer, typename xexpression_type::pointer>;
381 using const_pointer = typename xexpression_type::const_pointer;
382 using size_type = typename inner_types::size_type;
383 using difference_type = typename xexpression_type::difference_type;
384
385 static constexpr layout_type static_layout = inner_types::layout;
386 static constexpr bool contiguous_layout = static_layout != layout_type::dynamic;
387
388 static constexpr bool is_strided_view = detail::is_strided_view<xexpression_type, S...>::value;
389 static constexpr bool is_contiguous_view = contiguous_layout;
390
392 using inner_shape_type = typename iterable_base::inner_shape_type;
393 using shape_type = typename xview_shape_type<typename xexpression_type::shape_type, S...>::type;
394
395 using xexpression_inner_strides_type = xtl::mpl::eval_if_t<
397 detail::expr_inner_strides_type<xexpression_type>,
399
400 using xexpression_inner_backstrides_type = xtl::mpl::eval_if_t<
402 detail::expr_inner_backstrides_type<xexpression_type>,
404
405 using storage_type = typename inner_types::storage_type;
406
407 static constexpr bool has_trivial_strides = is_contiguous_view
408 && !xtl::disjunction<detail::is_xrange<S>...>::value;
409 using inner_strides_type = std::conditional_t<
410 has_trivial_strides,
411 typename detail::unwrap_offset_container<
412 xexpression_type::static_layout,
413 xexpression_inner_strides_type,
414 integral_count<S...>()>::type,
416
417 using inner_backstrides_type = std::conditional_t<
418 has_trivial_strides,
419 typename detail::unwrap_offset_container<
420 xexpression_type::static_layout,
421 xexpression_inner_backstrides_type,
422 integral_count<S...>()>::type,
424
427
428
429 using slice_type = std::tuple<S...>;
430
431 using stepper = typename iterable_base::stepper;
432 using const_stepper = typename iterable_base::const_stepper;
433
434 using linear_iterator = std::conditional_t<
436 std::conditional_t<is_const, typename xexpression_type::const_linear_iterator, typename xexpression_type::linear_iterator>,
437 typename iterable_base::linear_iterator>;
438 using const_linear_iterator = std::conditional_t<
440 typename xexpression_type::const_linear_iterator,
442
443 using reverse_linear_iterator = std::reverse_iterator<linear_iterator>;
444 using const_reverse_linear_iterator = std::reverse_iterator<const_linear_iterator>;
445
446 using container_iterator = pointer;
447 using const_container_iterator = const_pointer;
448 static constexpr std::size_t rank = SIZE_MAX;
449
450 // The FSL argument prevents the compiler from calling this constructor
451 // instead of the copy constructor when sizeof...(SL) == 0.
452 template <class CTA, class FSL, class... SL>
453 explicit xview(CTA&& e, FSL&& first_slice, SL&&... slices) noexcept;
454
455 xview(const xview&) = default;
456 self_type& operator=(const xview& rhs);
457
458 template <class E>
459 self_type& operator=(const xexpression<E>& e);
460
461 template <class E>
462 disable_xexpression<E, self_type>& operator=(const E& e);
463
464 const inner_shape_type& shape() const noexcept;
465 const slice_type& slices() const noexcept;
466 layout_type layout() const noexcept;
467 bool is_contiguous() const noexcept;
469
470 template <class T>
471 void fill(const T& value);
472
473 template <class... Args>
474 reference operator()(Args... args);
475 template <class... Args>
476 reference unchecked(Args... args);
477 template <class It>
478 reference element(It first, It last);
479
480 template <class... Args>
481 const_reference operator()(Args... args) const;
482 template <class... Args>
483 const_reference unchecked(Args... args) const;
484 template <class It>
485 const_reference element(It first, It last) const;
486
487 xexpression_type& expression() noexcept;
488 const xexpression_type& expression() const noexcept;
489
490 template <class ST>
491 bool broadcast_shape(ST& shape, bool reuse_cache = false) const;
492
493 template <class ST>
494 bool has_linear_assign(const ST& strides) const;
495
496 template <class ST, bool Enable = is_strided_view>
497 std::enable_if_t<!Enable, stepper> stepper_begin(const ST& shape);
498 template <class ST, bool Enable = is_strided_view>
499 std::enable_if_t<!Enable, stepper> stepper_end(const ST& shape, layout_type l);
500
501 template <class ST, bool Enable = is_strided_view>
502 std::enable_if_t<!Enable, const_stepper> stepper_begin(const ST& shape) const;
503 template <class ST, bool Enable = is_strided_view>
504 std::enable_if_t<!Enable, const_stepper> stepper_end(const ST& shape, layout_type l) const;
505
506 template <class ST, bool Enable = is_strided_view>
507 std::enable_if_t<Enable, stepper> stepper_begin(const ST& shape);
508 template <class ST, bool Enable = is_strided_view>
509 std::enable_if_t<Enable, stepper> stepper_end(const ST& shape, layout_type l);
510
511 template <class ST, bool Enable = is_strided_view>
512 std::enable_if_t<Enable, const_stepper> stepper_begin(const ST& shape) const;
513 template <class ST, bool Enable = is_strided_view>
514 std::enable_if_t<Enable, const_stepper> stepper_end(const ST& shape, layout_type l) const;
515
516 template <class T = xexpression_type>
517 std::enable_if_t<has_data_interface<T>::value, storage_type&> storage();
518
519 template <class T = xexpression_type>
520 std::enable_if_t<has_data_interface<T>::value, const storage_type&> storage() const;
521
522 template <class T = xexpression_type>
523 std::enable_if_t<has_data_interface<T>::value && is_strided_view, linear_iterator> linear_begin();
524
525 template <class T = xexpression_type>
526 std::enable_if_t<has_data_interface<T>::value && is_strided_view, linear_iterator> linear_end();
527
528 template <class T = xexpression_type>
529 std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_linear_iterator>
530 linear_begin() const;
531
532 template <class T = xexpression_type>
533 std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_linear_iterator>
534 linear_end() const;
535
536 template <class T = xexpression_type>
537 std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_linear_iterator>
538 linear_cbegin() const;
539
540 template <class T = xexpression_type>
541 std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_linear_iterator>
542 linear_cend() const;
543
544 template <class T = xexpression_type>
545 std::enable_if_t<has_data_interface<T>::value && is_strided_view, reverse_linear_iterator>
546 linear_rbegin();
547
548 template <class T = xexpression_type>
549 std::enable_if_t<has_data_interface<T>::value && is_strided_view, reverse_linear_iterator>
550 linear_rend();
551
552 template <class T = xexpression_type>
553 std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_reverse_linear_iterator>
554 linear_rbegin() const;
555
556 template <class T = xexpression_type>
557 std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_reverse_linear_iterator>
558 linear_rend() const;
559
560 template <class T = xexpression_type>
561 std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_reverse_linear_iterator>
562 linear_crbegin() const;
563
564 template <class T = xexpression_type>
565 std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_reverse_linear_iterator>
566 linear_crend() const;
567
568 template <class T = xexpression_type>
569 std::enable_if_t<has_data_interface<T>::value && is_strided_view, const inner_strides_type&>
570 strides() const;
571
572 template <class T = xexpression_type>
573 std::enable_if_t<has_data_interface<T>::value && is_strided_view, const inner_strides_type&>
574 backstrides() const;
575
576 template <class T = xexpression_type>
577 std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_pointer> data() const;
578
579 template <class T = xexpression_type>
580 std::enable_if_t<has_data_interface<T>::value && is_strided_view, pointer> data();
581
582 template <class T = xexpression_type>
583 std::enable_if_t<has_data_interface<T>::value && is_strided_view, std::size_t>
584 data_offset() const noexcept;
585
586 template <class It>
587 inline It data_xbegin_impl(It begin) const noexcept;
588
589 template <class It>
590 inline It data_xend_impl(It begin, layout_type l, size_type offset) const noexcept;
591 inline container_iterator data_xbegin() noexcept;
592 inline const_container_iterator data_xbegin() const noexcept;
593 inline container_iterator data_xend(layout_type l, size_type offset) noexcept;
594
595 inline const_container_iterator data_xend(layout_type l, size_type offset) const noexcept;
596
597 // Conversion operator enabled for statically "scalar" views
598 template <class ST = self_type, class = std::enable_if_t<is_xscalar<std::decay_t<ST>>::value, int>>
599 operator reference()
600 {
601 return (*this)();
602 }
603
604 template <class ST = self_type, class = std::enable_if_t<is_xscalar<std::decay_t<ST>>::value, int>>
605 operator const_reference() const
606 {
607 return (*this)();
608 }
609
610 size_type underlying_size(size_type dim) const;
611
612 xtl::xclosure_pointer<self_type&> operator&() &;
613 xtl::xclosure_pointer<const self_type&> operator&() const&;
614 xtl::xclosure_pointer<self_type> operator&() &&;
615
616 template <
617 class E,
618 class T = xexpression_type,
619 class = std::enable_if_t<has_data_interface<T>::value && is_contiguous_view, int>>
620 void assign_to(xexpression<E>& e, bool force_resize) const;
621
622 template <class E>
623 using rebind_t = xview<E, S...>;
624
625 template <class E>
626 rebind_t<E> build_view(E&& e) const;
627
628 //
629 // SIMD interface
630 //
631
632 template <class requested_type>
633 using simd_return_type = xt_simd::simd_return_type<value_type, requested_type>;
634
635 template <class T, class R>
636 using enable_simd_interface = std::enable_if_t<has_simd_interface<T>::value && is_strided_view, R>;
637
638 template <class align, class simd, class T = xexpression_type>
639 enable_simd_interface<T, void> store_simd(size_type i, const simd& e);
640
641 template <
642 class align,
643 class requested_type = value_type,
645 class T = xexpression_type>
647
648 template <class T = xexpression_type>
649 enable_simd_interface<T, reference> data_element(size_type i);
650
651 template <class T = xexpression_type>
652 enable_simd_interface<T, const_reference> data_element(size_type i) const;
653
654 template <class T = xexpression_type>
656
657 template <class T = xexpression_type>
658 enable_simd_interface<T, const_reference> flat(size_type i) const;
659
660 private:
661
662 // VS 2015 workaround (yes, really)
663 template <std::size_t I>
664 struct lesser_condition
665 {
666 static constexpr bool value = (I + newaxis_count_before<S...>(I + 1) < sizeof...(S));
667 };
668
669 CT m_e;
670 slice_type m_slices;
671 inner_shape_type m_shape;
672 mutable inner_strides_type m_strides;
673 mutable inner_backstrides_type m_backstrides;
674 mutable std::size_t m_data_offset;
675 mutable bool m_strides_computed;
676
677 template <class CTA, class FSL, class... SL>
678 explicit xview(std::true_type, CTA&& e, FSL&& first_slice, SL&&... slices) noexcept;
679
680 template <class CTA, class FSL, class... SL>
681 explicit xview(std::false_type, CTA&& e, FSL&& first_slice, SL&&... slices) noexcept;
682
683 template <class... Args>
684 auto make_index_sequence(Args... args) const noexcept;
685
686 void compute_strides(std::true_type) const;
687 void compute_strides(std::false_type) const;
688
689 reference access();
690
691 template <class Arg, class... Args>
692 reference access(Arg arg, Args... args);
693
694 const_reference access() const;
695
696 template <class Arg, class... Args>
697 const_reference access(Arg arg, Args... args) const;
698
700 reference unchecked_impl(std::index_sequence<I...>, Args... args);
701
703 const_reference unchecked_impl(std::index_sequence<I...>, Args... args) const;
704
706 reference access_impl(std::index_sequence<I...>, Args... args);
707
709 const_reference access_impl(std::index_sequence<I...>, Args... args) const;
710
712 std::enable_if_t<lesser_condition<I>::value, size_type> index(Args... args) const;
713
715 std::enable_if_t<!lesser_condition<I>::value, size_type> index(Args... args) const;
716
718 size_type sliced_access(const xslice<T>& slice) const;
719
721 size_type sliced_access(const xslice<T>& slice, Arg arg, Args... args) const;
722
724 disable_xslice<T, size_type> sliced_access(const T& squeeze, Args...) const;
725
727
728 template <class It>
729 base_index_type make_index(It first, It last) const;
730
731 void assign_temporary_impl(temporary_type&& tmp);
732
733 template <std::size_t... I>
734 std::size_t data_offset_impl(std::index_sequence<I...>) const noexcept;
735
736 template <std::size_t... I>
737 auto compute_strides_impl(std::index_sequence<I...>) const noexcept;
738
739 inner_shape_type compute_shape(std::true_type) const;
740 inner_shape_type compute_shape(std::false_type) const;
741
742 template <class E, std::size_t... I>
743 rebind_t<E> build_view_impl(E&& e, std::index_sequence<I...>) const;
744
745 friend class xview_semantic<xview<CT, S...>>;
746 };
747
748 template <class E, class... S>
749 auto view(E&& e, S&&... slices);
750
751 template <class E>
752 auto row(E&& e, std::ptrdiff_t index);
753
754 template <class E>
755 auto col(E&& e, std::ptrdiff_t index);
756
757 /*****************************
758 * xview_stepper declaration *
759 *****************************/
760
761 namespace detail
762 {
763 template <class V>
764 struct get_stepper_impl
765 {
766 using xexpression_type = typename V::xexpression_type;
767 using type = typename xexpression_type::stepper;
768 };
769
770 template <class V>
771 struct get_stepper_impl<const V>
772 {
773 using xexpression_type = typename V::xexpression_type;
774 using type = typename xexpression_type::const_stepper;
775 };
776 }
777
778 template <class V>
779 using get_stepper = typename detail::get_stepper_impl<V>::type;
780
781 template <bool is_const, class CT, class... S>
783 {
784 public:
785
786 using view_type = std::conditional_t<is_const, const xview<CT, S...>, xview<CT, S...>>;
787 using substepper_type = get_stepper<view_type>;
788
789 using value_type = typename substepper_type::value_type;
790 using reference = typename substepper_type::reference;
791 using pointer = typename substepper_type::pointer;
792 using difference_type = typename substepper_type::difference_type;
793 using size_type = typename view_type::size_type;
794
795 using shape_type = typename substepper_type::shape_type;
796
797 xview_stepper() = default;
799 view_type* view,
800 substepper_type it,
801 size_type offset,
802 bool end = false,
803 layout_type l = XTENSOR_DEFAULT_TRAVERSAL
804 );
805
806 reference operator*() const;
807
808 void step(size_type dim);
809 void step_back(size_type dim);
810 void step(size_type dim, size_type n);
811 void step_back(size_type dim, size_type n);
812 void reset(size_type dim);
813 void reset_back(size_type dim);
814
815 void to_begin();
816 void to_end(layout_type l);
817
818 private:
819
820 bool is_newaxis_slice(size_type index) const noexcept;
821 void to_end_impl(layout_type l);
822
823 template <class F>
824 void common_step_forward(size_type dim, F f);
825 template <class F>
826 void common_step_backward(size_type dim, F f);
827
828 template <class F>
829 void common_step_forward(size_type dim, size_type n, F f);
830 template <class F>
831 void common_step_backward(size_type dim, size_type n, F f);
832
833 template <class F>
834 void common_reset(size_type dim, F f, bool backwards);
835
836 view_type* p_view;
837 substepper_type m_it;
838 size_type m_offset;
839 std::array<std::size_t, sizeof...(S)> m_index_keeper;
840 };
841
842 // meta-function returning the shape type for an xview
843 template <class ST, class... S>
845 {
846 using type = ST;
847 };
848
849 template <class I, std::size_t L, class... S>
850 struct xview_shape_type<std::array<I, L>, S...>
851 {
852 using type = std::array<I, L - integral_count<S...>() + newaxis_count<S...>()>;
853 };
854
855 template <std::size_t... I, class... S>
857 {
858 using type = typename xview_shape_type<std::array<std::size_t, sizeof...(I)>, S...>::type;
859 };
860
861 /************************
862 * xview implementation *
863 ************************/
864
879 template <class CT, class... S>
880 template <class CTA, class FSL, class... SL>
882 : xview(
883 std::integral_constant<bool, has_trivial_strides>{},
884 std::forward<CTA>(e),
885 std::forward<FSL>(first_slice),
886 std::forward<SL>(slices)...
887 )
888 {
889 }
890
891 // trivial strides initializer
892 template <class CT, class... S>
893 template <class CTA, class FSL, class... SL>
894 xview<CT, S...>::xview(std::true_type, CTA&& e, FSL&& first_slice, SL&&... slices) noexcept
895 : m_e(std::forward<CTA>(e))
896 , m_slices(std::forward<FSL>(first_slice), std::forward<SL>(slices)...)
897 , m_shape(compute_shape(detail::is_sequence_view<inner_shape_type>{}))
898 , m_strides(m_e.strides())
899 , m_backstrides(m_e.backstrides())
900 , m_data_offset(data_offset_impl(std::make_index_sequence<sizeof...(S)>()))
901 , m_strides_computed(true)
902 {
903 }
904
905 template <class CT, class... S>
906 template <class CTA, class FSL, class... SL>
907 xview<CT, S...>::xview(std::false_type, CTA&& e, FSL&& first_slice, SL&&... slices) noexcept
908 : m_e(std::forward<CTA>(e))
909 , m_slices(std::forward<FSL>(first_slice), std::forward<SL>(slices)...)
910 , m_shape(compute_shape(std::false_type{}))
911 , m_strides_computed(false)
912 {
913 }
914
916
917 template <class CT, class... S>
918 inline auto xview<CT, S...>::operator=(const xview& rhs) -> self_type&
919 {
920 temporary_type tmp(rhs);
921 return this->assign_temporary(std::move(tmp));
922 }
923
931 template <class CT, class... S>
932 template <class E>
934 {
935 return semantic_base::operator=(e);
936 }
937
939
940 template <class CT, class... S>
941 template <class E>
943 {
944 this->fill(e);
945 return *this;
946 }
947
955 template <class CT, class... S>
956 inline auto xview<CT, S...>::shape() const noexcept -> const inner_shape_type&
957 {
958 return m_shape;
959 }
960
964 template <class CT, class... S>
965 inline auto xview<CT, S...>::slices() const noexcept -> const slice_type&
966 {
967 return m_slices;
968 }
969
973 template <class CT, class... S>
975 {
976 return xtl::mpl::static_if<is_strided_view>(
977 [&](auto self)
978 {
979 if (static_layout != layout_type::dynamic)
980 {
981 return static_layout;
982 }
983 else
984 {
985 bool strides_match = do_strides_match(
986 self(this)->shape(),
987 self(this)->strides(),
988 self(this)->m_e.layout(),
989 true
990 );
991 return strides_match ? self(this)->m_e.layout() : layout_type::dynamic;
992 }
993 },
994 /* else */
995 [&](auto /*self*/)
996 {
998 }
999 );
1000 }
1001
1002 template <class CT, class... S>
1004 {
1005 return layout() != layout_type::dynamic;
1006 }
1007
1009
1014
1019 template <class CT, class... S>
1020 template <class T>
1021 inline void xview<CT, S...>::fill(const T& value)
1022 {
1023 xtl::mpl::static_if<static_layout != layout_type::dynamic>(
1024 [&](auto self)
1025 {
1026 std::fill(self(this)->linear_begin(), self(this)->linear_end(), value);
1027 },
1028 /*else*/
1029 [&](auto self)
1030 {
1031 std::fill(self(this)->begin(), self(this)->end(), value);
1032 }
1033 );
1034 }
1035
1042 template <class CT, class... S>
1043 template <class... Args>
1044 inline auto xview<CT, S...>::operator()(Args... args) -> reference
1045 {
1046 XTENSOR_TRY(check_index(shape(), args...));
1047 XTENSOR_CHECK_DIMENSION(shape(), args...);
1048 // The static cast prevents the compiler from instantiating the template methods with signed integers,
1049 // leading to warning about signed/unsigned conversions in the deeper layers of the access methods
1050 return access(static_cast<size_type>(args)...);
1051 }
1052
1072 template <class CT, class... S>
1073 template <class... Args>
1074 inline auto xview<CT, S...>::unchecked(Args... args) -> reference
1075 {
1076 return unchecked_impl(make_index_sequence(args...), static_cast<size_type>(args)...);
1077 }
1078
1079 template <class CT, class... S>
1080 template <class It>
1081 inline auto xview<CT, S...>::element(It first, It last) -> reference
1082 {
1083 XTENSOR_TRY(check_element_index(shape(), first, last));
1084 // TODO: avoid memory allocation
1085 auto index = make_index(first, last);
1086 return m_e.element(index.cbegin(), index.cend());
1087 }
1088
1095 template <class CT, class... S>
1096 template <class... Args>
1097 inline auto xview<CT, S...>::operator()(Args... args) const -> const_reference
1098 {
1099 XTENSOR_TRY(check_index(shape(), args...));
1100 XTENSOR_CHECK_DIMENSION(shape(), args...);
1101 // The static cast prevents the compiler from instantiating the template methods with signed integers,
1102 // leading to warning about signed/unsigned conversions in the deeper layers of the access methods
1103 return access(static_cast<size_type>(args)...);
1104 }
1105
1125 template <class CT, class... S>
1126 template <class... Args>
1127 inline auto xview<CT, S...>::unchecked(Args... args) const -> const_reference
1128 {
1129 return unchecked_impl(make_index_sequence(args...), static_cast<size_type>(args)...);
1130 }
1131
1132 template <class CT, class... S>
1133 template <class It>
1134 inline auto xview<CT, S...>::element(It first, It last) const -> const_reference
1135 {
1136 // TODO: avoid memory allocation
1137 auto index = make_index(first, last);
1138 return m_e.element(index.cbegin(), index.cend());
1139 }
1140
1144 template <class CT, class... S>
1145 inline auto xview<CT, S...>::expression() noexcept -> xexpression_type&
1146 {
1147 return m_e;
1148 }
1149
1153 template <class CT, class... S>
1154 inline auto xview<CT, S...>::expression() const noexcept -> const xexpression_type&
1155 {
1156 return m_e;
1157 }
1158
1164 template <class CT, class... S>
1165 template <class T>
1166 inline auto xview<CT, S...>::storage() -> std::enable_if_t<has_data_interface<T>::value, storage_type&>
1167 {
1168 return m_e.storage();
1169 }
1170
1171 template <class CT, class... S>
1172 template <class T>
1173 inline auto xview<CT, S...>::storage() const
1174 -> std::enable_if_t<has_data_interface<T>::value, const storage_type&>
1175 {
1176 return m_e.storage();
1177 }
1178
1179 template <class CT, class... S>
1180 template <class T>
1181 auto xview<CT, S...>::linear_begin()
1182 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, linear_iterator>
1183 {
1184 return m_e.storage().begin() + data_offset();
1185 }
1186
1187 template <class CT, class... S>
1188 template <class T>
1189 auto xview<CT, S...>::linear_end()
1190 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, linear_iterator>
1191 {
1192 return m_e.storage().begin() + data_offset() + this->size();
1193 }
1194
1195 template <class CT, class... S>
1196 template <class T>
1197 auto xview<CT, S...>::linear_begin() const
1198 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_linear_iterator>
1199 {
1200 return linear_cbegin();
1201 }
1202
1203 template <class CT, class... S>
1204 template <class T>
1205 auto xview<CT, S...>::linear_end() const
1206 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_linear_iterator>
1207 {
1208 return linear_cend();
1209 }
1210
1211 template <class CT, class... S>
1212 template <class T>
1213 auto xview<CT, S...>::linear_cbegin() const
1214 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_linear_iterator>
1215 {
1216 return m_e.storage().cbegin() + data_offset();
1217 }
1218
1219 template <class CT, class... S>
1220 template <class T>
1221 auto xview<CT, S...>::linear_cend() const
1222 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_linear_iterator>
1223 {
1224 return m_e.storage().cbegin() + data_offset() + this->size();
1225 }
1226
1227 template <class CT, class... S>
1228 template <class T>
1229 auto xview<CT, S...>::linear_rbegin()
1230 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, reverse_linear_iterator>
1231 {
1232 return reverse_linear_iterator(linear_end());
1233 }
1234
1235 template <class CT, class... S>
1236 template <class T>
1237 auto xview<CT, S...>::linear_rend()
1238 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, reverse_linear_iterator>
1239 {
1240 return reverse_linear_iterator(linear_begin());
1241 }
1242
1243 template <class CT, class... S>
1244 template <class T>
1245 auto xview<CT, S...>::linear_rbegin() const
1246 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_reverse_linear_iterator>
1247 {
1248 return linear_crbegin();
1249 }
1250
1251 template <class CT, class... S>
1252 template <class T>
1253 auto xview<CT, S...>::linear_rend() const
1254 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_reverse_linear_iterator>
1255 {
1256 return linear_crend();
1257 }
1258
1259 template <class CT, class... S>
1260 template <class T>
1261 auto xview<CT, S...>::linear_crbegin() const
1262 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_reverse_linear_iterator>
1263 {
1264 return const_reverse_linear_iterator(linear_end());
1265 }
1266
1267 template <class CT, class... S>
1268 template <class T>
1269 auto xview<CT, S...>::linear_crend() const
1270 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_reverse_linear_iterator>
1271 {
1272 return const_reverse_linear_iterator(linear_begin());
1273 }
1274
1278 template <class CT, class... S>
1279 template <class T>
1281 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, const inner_strides_type&>
1282 {
1283 if (!m_strides_computed)
1284 {
1285 compute_strides(std::integral_constant<bool, has_trivial_strides>{});
1286 m_strides_computed = true;
1287 }
1288 return m_strides;
1289 }
1290
1291 template <class CT, class... S>
1292 template <class T>
1294 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, const inner_strides_type&>
1295 {
1296 if (!m_strides_computed)
1297 {
1298 compute_strides(std::integral_constant<bool, has_trivial_strides>{});
1299 m_strides_computed = true;
1300 }
1301 return m_backstrides;
1302 }
1303
1307 template <class CT, class... S>
1308 template <class T>
1310 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, const_pointer>
1311 {
1312 return m_e.data();
1313 }
1314
1315 template <class CT, class... S>
1316 template <class T>
1317 inline auto xview<CT, S...>::data()
1318 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, pointer>
1319 {
1320 return m_e.data();
1321 }
1322
1323 template <class CT, class... S>
1324 template <std::size_t... I>
1325 inline std::size_t xview<CT, S...>::data_offset_impl(std::index_sequence<I...>) const noexcept
1326 {
1327 auto temp = std::array<std::ptrdiff_t, sizeof...(S)>(
1328 {(static_cast<ptrdiff_t>(xt::value(std::get<I>(m_slices), 0)))...}
1329 );
1330
1331 std::ptrdiff_t result = 0;
1332 std::size_t i = 0;
1333 for (; i < std::min(sizeof...(S), m_e.strides().size()); ++i)
1334 {
1335 result += temp[i] * m_e.strides()[i - newaxis_count_before<S...>(i)];
1336 }
1337 for (; i < sizeof...(S); ++i)
1338 {
1339 result += temp[i];
1340 }
1341 return static_cast<std::size_t>(result) + m_e.data_offset();
1342 }
1343
1347 template <class CT, class... S>
1348 template <class T>
1350 -> std::enable_if_t<has_data_interface<T>::value && is_strided_view, std::size_t>
1351 {
1352 if (!m_strides_computed)
1353 {
1354 compute_strides(std::integral_constant<bool, has_trivial_strides>{});
1355 m_strides_computed = true;
1356 }
1357 return m_data_offset;
1358 }
1359
1361
1362 template <class CT, class... S>
1363 inline auto xview<CT, S...>::underlying_size(size_type dim) const -> size_type
1364 {
1365 return m_e.shape()[dim];
1366 }
1367
1368 template <class CT, class... S>
1369 inline auto xview<CT, S...>::operator&() & -> xtl::xclosure_pointer<self_type&>
1370 {
1371 return xtl::closure_pointer(*this);
1372 }
1373
1374 template <class CT, class... S>
1375 inline auto xview<CT, S...>::operator&() const& -> xtl::xclosure_pointer<const self_type&>
1376 {
1377 return xtl::closure_pointer(*this);
1378 }
1379
1380 template <class CT, class... S>
1381 inline auto xview<CT, S...>::operator&() && -> xtl::xclosure_pointer<self_type>
1382 {
1383 return xtl::closure_pointer(std::move(*this));
1384 }
1385
1396 template <class CT, class... S>
1397 template <class ST>
1398 inline bool xview<CT, S...>::broadcast_shape(ST& shape, bool) const
1399 {
1400 return xt::broadcast_shape(m_shape, shape);
1401 }
1402
1408 template <class CT, class... S>
1409 template <class ST>
1411 {
1412 return xtl::mpl::static_if<is_strided_view>(
1413 [&](auto self)
1414 {
1415 return str.size() == self(this)->strides().size()
1416 && std::equal(str.cbegin(), str.cend(), self(this)->strides().begin());
1417 },
1418 /*else*/
1419 [](auto /*self*/)
1420 {
1421 return false;
1422 }
1423 );
1424 }
1425
1427
1428 template <class CT, class... S>
1429 template <class It>
1430 inline It xview<CT, S...>::data_xbegin_impl(It begin) const noexcept
1431 {
1432 return begin + data_offset();
1433 }
1434
1435 template <class CT, class... S>
1436 template <class It>
1437 inline It xview<CT, S...>::data_xend_impl(It begin, layout_type l, size_type offset) const noexcept
1438 {
1439 return strided_data_end(*this, begin, l, offset);
1440 }
1441
1442 template <class CT, class... S>
1443 inline auto xview<CT, S...>::data_xbegin() noexcept -> container_iterator
1444 {
1445 return data_xbegin_impl(data());
1446 }
1447
1448 template <class CT, class... S>
1449 inline auto xview<CT, S...>::data_xbegin() const noexcept -> const_container_iterator
1450 {
1451 return data_xbegin_impl(data());
1452 }
1453
1454 template <class CT, class... S>
1455 inline auto xview<CT, S...>::data_xend(layout_type l, size_type offset) noexcept -> container_iterator
1456 {
1457 return data_xend_impl(data() + data_offset(), l, offset);
1458 }
1459
1460 template <class CT, class... S>
1461 inline auto xview<CT, S...>::data_xend(layout_type l, size_type offset) const noexcept
1462 -> const_container_iterator
1463 {
1464 return data_xend_impl(data() + data_offset(), l, offset);
1465 }
1466
1467 // Assign to operator enabled for contigous views
1468 template <class CT, class... S>
1469 template <class E, class T, class>
1470 void xview<CT, S...>::assign_to(xexpression<E>& e, bool force_resize) const
1471 {
1472 auto& de = e.derived_cast();
1473 de.resize(shape(), force_resize);
1474 std::copy(data() + data_offset(), data() + data_offset() + de.size(), de.template begin<static_layout>());
1475 }
1476
1477 template <class CT, class... S>
1478 template <class E, std::size_t... I>
1479 inline auto xview<CT, S...>::build_view_impl(E&& e, std::index_sequence<I...>) const -> rebind_t<E>
1480 {
1481 return rebind_t<E>(std::forward<E>(e), std::get<I>(m_slices)...);
1482 }
1483
1484 template <class CT, class... S>
1485 template <class E>
1486 inline auto xview<CT, S...>::build_view(E&& e) const -> rebind_t<E>
1487 {
1488 return build_view_impl(std::forward<E>(e), std::make_index_sequence<sizeof...(S)>());
1489 }
1490
1491 template <class CT, class... S>
1492 template <class align, class simd, class T>
1493 inline auto xview<CT, S...>::store_simd(size_type i, const simd& e) -> enable_simd_interface<T, void>
1494 {
1495 return m_e.template store_simd<xt_simd::unaligned_mode>(data_offset() + i, e);
1496 }
1497
1498 template <class CT, class... S>
1499 template <class align, class requested_type, std::size_t N, class T>
1500 inline auto xview<CT, S...>::load_simd(size_type i) const
1501 -> enable_simd_interface<T, simd_return_type<requested_type>>
1502 {
1503 return m_e.template load_simd<xt_simd::unaligned_mode, requested_type>(data_offset() + i);
1504 }
1505
1506 template <class CT, class... S>
1507 template <class T>
1508 inline auto xview<CT, S...>::data_element(size_type i) -> enable_simd_interface<T, reference>
1509 {
1510 return m_e.data_element(data_offset() + i);
1511 }
1512
1513 template <class CT, class... S>
1514 template <class T>
1515 inline auto xview<CT, S...>::data_element(size_type i) const -> enable_simd_interface<T, const_reference>
1516 {
1517 return m_e.data_element(data_offset() + i);
1518 }
1519
1520 template <class CT, class... S>
1521 template <class T>
1522 inline auto xview<CT, S...>::flat(size_type i) -> enable_simd_interface<T, reference>
1523 {
1524 XTENSOR_ASSERT(is_contiguous());
1525 return m_e.flat(data_offset() + i);
1526 }
1527
1528 template <class CT, class... S>
1529 template <class T>
1530 inline auto xview<CT, S...>::flat(size_type i) const -> enable_simd_interface<T, const_reference>
1531 {
1532 XTENSOR_ASSERT(is_contiguous());
1533 return m_e.flat(data_offset() + i);
1534 }
1535
1536 template <class CT, class... S>
1537 template <class... Args>
1538 inline auto xview<CT, S...>::make_index_sequence(Args...) const noexcept
1539 {
1540 return std::make_index_sequence<
1541 (sizeof...(Args) + integral_count<S...>() > newaxis_count<S...>()
1542 ? sizeof...(Args) + integral_count<S...>() - newaxis_count<S...>()
1543 : 0)>();
1544 }
1545
1546 template <class CT, class... S>
1547 template <std::size_t... I>
1548 inline auto xview<CT, S...>::compute_strides_impl(std::index_sequence<I...>) const noexcept
1549 {
1550 std::size_t original_dim = m_e.dimension();
1551 return std::array<std::ptrdiff_t, sizeof...(I)>(
1552 {(static_cast<std::ptrdiff_t>(xt::step_size(std::get<integral_skip<S...>(I)>(m_slices), 1))
1553 * ((integral_skip<S...>(I) - newaxis_count_before<S...>(integral_skip<S...>(I))) < original_dim
1554 ? m_e.strides()[integral_skip<S...>(I) - newaxis_count_before<S...>(integral_skip<S...>(I))]
1555 : 1))...}
1556 );
1557 }
1558
1559 template <class CT, class... S>
1560 inline void xview<CT, S...>::compute_strides(std::false_type) const
1561 {
1562 m_strides = xtl::make_sequence<inner_strides_type>(this->dimension(), 0);
1563 m_backstrides = xtl::make_sequence<inner_strides_type>(this->dimension(), 0);
1564
1565 constexpr std::size_t n_strides = sizeof...(S) - integral_count<S...>();
1566
1567 auto slice_strides = compute_strides_impl(std::make_index_sequence<n_strides>());
1568
1569 for (std::size_t i = 0; i < n_strides; ++i)
1570 {
1571 m_strides[i] = slice_strides[i];
1572 // adapt strides for shape[i] == 1 to make consistent with rest of xtensor
1573 detail::adapt_strides(shape(), m_strides, &m_backstrides, i);
1574 }
1575 for (std::size_t i = n_strides; i < this->dimension(); ++i)
1576 {
1577 m_strides[i] = m_e.strides()[i + integral_count<S...>() - newaxis_count<S...>()];
1578 detail::adapt_strides(shape(), m_strides, &m_backstrides, i);
1579 }
1580
1581 m_data_offset = data_offset_impl(std::make_index_sequence<sizeof...(S)>());
1582 }
1583
1584 template <class CT, class... S>
1585 inline void xview<CT, S...>::compute_strides(std::true_type) const
1586 {
1587 }
1588
1589 template <class CT, class... S>
1590 inline auto xview<CT, S...>::access() -> reference
1591 {
1592 return access_impl(make_index_sequence());
1593 }
1594
1595 template <class CT, class... S>
1596 template <class Arg, class... Args>
1597 inline auto xview<CT, S...>::access(Arg arg, Args... args) -> reference
1598 {
1599 if (sizeof...(Args) >= this->dimension())
1600 {
1601 return access(args...);
1602 }
1603 return access_impl(make_index_sequence(arg, args...), arg, args...);
1604 }
1605
1606 template <class CT, class... S>
1607 inline auto xview<CT, S...>::access() const -> const_reference
1608 {
1609 return access_impl(make_index_sequence());
1610 }
1611
1612 template <class CT, class... S>
1613 template <class Arg, class... Args>
1614 inline auto xview<CT, S...>::access(Arg arg, Args... args) const -> const_reference
1615 {
1616 if (sizeof...(Args) >= this->dimension())
1617 {
1618 return access(args...);
1619 }
1620 return access_impl(make_index_sequence(arg, args...), arg, args...);
1621 }
1622
1623 template <class CT, class... S>
1624 template <typename std::decay_t<CT>::size_type... I, class... Args>
1625 inline auto xview<CT, S...>::unchecked_impl(std::index_sequence<I...>, Args... args) -> reference
1626 {
1627 return m_e.unchecked(index<I>(args...)...);
1628 }
1629
1630 template <class CT, class... S>
1631 template <typename std::decay_t<CT>::size_type... I, class... Args>
1632 inline auto xview<CT, S...>::unchecked_impl(std::index_sequence<I...>, Args... args) const
1633 -> const_reference
1634 {
1635 return m_e.unchecked(index<I>(args...)...);
1636 }
1637
1638 template <class CT, class... S>
1639 template <typename std::decay_t<CT>::size_type... I, class... Args>
1640 inline auto xview<CT, S...>::access_impl(std::index_sequence<I...>, Args... args) -> reference
1641 {
1642 return m_e(index<I>(args...)...);
1643 }
1644
1645 template <class CT, class... S>
1646 template <typename std::decay_t<CT>::size_type... I, class... Args>
1647 inline auto xview<CT, S...>::access_impl(std::index_sequence<I...>, Args... args) const -> const_reference
1648 {
1649 return m_e(index<I>(args...)...);
1650 }
1651
1652 template <class CT, class... S>
1653 template <typename std::decay_t<CT>::size_type I, class... Args>
1654 inline auto xview<CT, S...>::index(Args... args) const
1655 -> std::enable_if_t<lesser_condition<I>::value, size_type>
1656 {
1657 return sliced_access<I - integral_count_before<S...>(I) + newaxis_count_before<S...>(I + 1)>(
1658 std::get<I + newaxis_count_before<S...>(I + 1)>(m_slices),
1659 args...
1660 );
1661 }
1662
1663 template <class CT, class... S>
1664 template <typename std::decay_t<CT>::size_type I, class... Args>
1665 inline auto xview<CT, S...>::index(Args... args) const
1666 -> std::enable_if_t<!lesser_condition<I>::value, size_type>
1667 {
1668 return argument<I - integral_count<S...>() + newaxis_count<S...>()>(args...);
1669 }
1670
1671 template <class CT, class... S>
1672 template <typename std::decay_t<CT>::size_type I, class T>
1673 inline auto xview<CT, S...>::sliced_access(const xslice<T>& slice) const -> size_type
1674 {
1675 return static_cast<size_type>(slice.derived_cast()(0));
1676 }
1677
1678 template <class CT, class... S>
1679 template <typename std::decay_t<CT>::size_type I, class T, class Arg, class... Args>
1680 inline auto xview<CT, S...>::sliced_access(const xslice<T>& slice, Arg arg, Args... args) const -> size_type
1681 {
1682 using ST = typename T::size_type;
1683 return static_cast<size_type>(
1684 slice.derived_cast()(argument<I>(static_cast<ST>(arg), static_cast<ST>(args)...))
1685 );
1686 }
1687
1688 template <class CT, class... S>
1689 template <typename std::decay_t<CT>::size_type I, class T, class... Args>
1690 inline auto xview<CT, S...>::sliced_access(const T& squeeze, Args...) const -> disable_xslice<T, size_type>
1691 {
1692 return static_cast<size_type>(squeeze);
1693 }
1694
1695 template <class CT, class... S>
1696 template <class It>
1697 inline auto xview<CT, S...>::make_index(It first, It last) const -> base_index_type
1698 {
1699 auto index = xtl::make_sequence<base_index_type>(m_e.dimension(), 0);
1700 using diff_type = typename std::iterator_traits<It>::difference_type;
1701 using ivalue_type = typename base_index_type::value_type;
1702 auto func1 = [&first](const auto& s) noexcept
1703 {
1704 return get_slice_value(s, first);
1705 };
1706 auto func2 = [](const auto& s) noexcept
1707 {
1708 return xt::value(s, 0);
1709 };
1710
1711 auto s = static_cast<diff_type>(
1712 (std::min)(static_cast<size_type>(std::distance(first, last)), this->dimension())
1713 );
1714 auto first_copy = last - s;
1715 for (size_type i = 0; i != m_e.dimension(); ++i)
1716 {
1717 size_type k = newaxis_skip<S...>(i);
1718
1719 // need to advance captured `first`
1720 first = first_copy;
1721 std::advance(first, static_cast<diff_type>(k - xt::integral_count_before<S...>(i)));
1722
1723 if (first < last)
1724 {
1725 index[i] = k < sizeof...(S) ? apply<size_type>(k, func1, m_slices)
1726 : static_cast<ivalue_type>(*first);
1727 }
1728 else
1729 {
1730 index[i] = k < sizeof...(S) ? apply<size_type>(k, func2, m_slices) : ivalue_type(0);
1731 }
1732 }
1733 return index;
1734 }
1735
1736 template <class CT, class... S>
1737 inline auto xview<CT, S...>::compute_shape(std::true_type) const -> inner_shape_type
1738 {
1739 return inner_shape_type(m_e.shape());
1740 }
1741
1742 template <class CT, class... S>
1743 inline auto xview<CT, S...>::compute_shape(std::false_type) const -> inner_shape_type
1744 {
1745 std::size_t dim = m_e.dimension() - integral_count<S...>() + newaxis_count<S...>();
1746 auto shape = xtl::make_sequence<inner_shape_type>(dim, 0);
1747 auto func = [](const auto& s) noexcept
1748 {
1749 return get_size(s);
1750 };
1751 for (size_type i = 0; i != dim; ++i)
1752 {
1753 size_type index = integral_skip<S...>(i);
1754 shape[i] = index < sizeof...(S) ? apply<size_type>(index, func, m_slices)
1755 : m_e.shape()[index - newaxis_count_before<S...>(index)];
1756 }
1757 return shape;
1758 }
1759
1760 namespace xview_detail
1761 {
1762 template <class V, class T>
1763 inline void run_assign_temporary_impl(V& v, const T& t, std::true_type /* enable strided assign */)
1764 {
1765 strided_loop_assigner<true>::run(v, t);
1766 }
1767
1768 template <class V, class T>
1769 inline void
1770 run_assign_temporary_impl(V& v, const T& t, std::false_type /* fallback to iterator assign */)
1771 {
1772 std::copy(t.cbegin(), t.cend(), v.begin());
1773 }
1774 }
1775
1776 template <class CT, class... S>
1777 inline void xview<CT, S...>::assign_temporary_impl(temporary_type&& tmp)
1778 {
1779 constexpr bool fast_assign = detail::is_strided_view<xexpression_type, S...>::value
1780 && xassign_traits<xview<CT, S...>, temporary_type>::simd_strided_assign();
1781 xview_detail::run_assign_temporary_impl(*this, tmp, std::integral_constant<bool, fast_assign>{});
1782 }
1783
1784 namespace detail
1785 {
1786 template <class E, class... S>
1787 inline std::size_t get_underlying_shape_index(std::size_t I)
1788 {
1789 return I - newaxis_count_before<get_slice_type<E, S>...>(I);
1790 }
1791
1792 template <class... S>
1793 struct check_slice;
1794
1795 template <>
1796 struct check_slice<>
1797 {
1798 using type = void_t<>;
1799 };
1800
1801 template <class S, class... SL>
1802 struct check_slice<S, SL...>
1803 {
1804 static_assert(!std::is_same<S, xellipsis_tag>::value, "ellipsis not supported vith xview");
1805 using type = typename check_slice<SL...>::type;
1806 };
1807
1808 template <class E, std::size_t... I, class... S>
1809 inline auto make_view_impl(E&& e, std::index_sequence<I...>, S&&... slices)
1810 {
1811 // Checks that no ellipsis slice is used
1812 using view_type = xview<xtl::closure_type_t<E>, get_slice_type<std::decay_t<E>, S>...>;
1813 return view_type(
1814 std::forward<E>(e),
1815 get_slice_implementation(
1816 e,
1817 std::forward<S>(slices),
1818 get_underlying_shape_index<std::decay_t<E>, S...>(I)
1819 )...
1820 );
1821 }
1822 }
1823
1833 template <class E, class... S>
1834 inline auto view(E&& e, S&&... slices)
1835 {
1836 return detail::make_view_impl(
1837 std::forward<E>(e),
1838 std::make_index_sequence<sizeof...(S)>(),
1839 std::forward<S>(slices)...
1840 );
1841 }
1842
1843 namespace detail
1844 {
1845 class row_impl
1846 {
1847 public:
1848
1849 template <class E>
1850 inline static auto make(E&& e, const std::ptrdiff_t index)
1851 {
1852 const auto shape = e.shape();
1853 check_dimension(shape);
1854 return view(e, index, xt::all());
1855 }
1856
1857 private:
1858
1859 template <class S>
1860 inline static void check_dimension(const S& shape)
1861 {
1862 if (shape.size() != 2)
1863 {
1864 XTENSOR_THROW(
1865 std::invalid_argument,
1866 "A row can only be accessed on an expression with exact two dimensions"
1867 );
1868 }
1869 }
1870
1871 template <class T, std::size_t N>
1872 inline static void check_dimension(const std::array<T, N>&)
1873 {
1874 static_assert(N == 2, "A row can only be accessed on an expression with exact two dimensions");
1875 }
1876 };
1877
1878 class column_impl
1879 {
1880 public:
1881
1882 template <class E>
1883 inline static auto make(E&& e, const std::ptrdiff_t index)
1884 {
1885 const auto shape = e.shape();
1886 check_dimension(shape);
1887 return view(e, xt::all(), index);
1888 }
1889
1890 private:
1891
1892 template <class S>
1893 inline static void check_dimension(const S& shape)
1894 {
1895 if (shape.size() != 2)
1896 {
1897 XTENSOR_THROW(
1898 std::invalid_argument,
1899 "A column can only be accessed on an expression with exact two dimensions"
1900 );
1901 }
1902 }
1903
1904 template <class T, std::size_t N>
1905 inline static void check_dimension(const std::array<T, N>&)
1906 {
1907 static_assert(N == 2, "A column can only be accessed on an expression with exact two dimensions");
1908 }
1909 };
1910 }
1911
1921 template <class E>
1922 inline auto row(E&& e, std::ptrdiff_t index)
1923 {
1924 return detail::row_impl::make(e, index);
1925 }
1926
1936 template <class E>
1937 inline auto col(E&& e, std::ptrdiff_t index)
1938 {
1939 return detail::column_impl::make(e, index);
1940 }
1941
1942 /***************
1943 * stepper api *
1944 ***************/
1945
1946 template <class CT, class... S>
1947 template <class ST, bool Enable>
1948 inline auto xview<CT, S...>::stepper_begin(const ST& shape) -> std::enable_if_t<!Enable, stepper>
1949 {
1950 size_type offset = shape.size() - this->dimension();
1951 return stepper(this, m_e.stepper_begin(m_e.shape()), offset);
1952 }
1953
1954 template <class CT, class... S>
1955 template <class ST, bool Enable>
1956 inline auto xview<CT, S...>::stepper_end(const ST& shape, layout_type l)
1957 -> std::enable_if_t<!Enable, stepper>
1958 {
1959 size_type offset = shape.size() - this->dimension();
1960 return stepper(this, m_e.stepper_end(m_e.shape(), l), offset, true, l);
1961 }
1962
1963 template <class CT, class... S>
1964 template <class ST, bool Enable>
1965 inline auto xview<CT, S...>::stepper_begin(const ST& shape) const
1966 -> std::enable_if_t<!Enable, const_stepper>
1967 {
1968 size_type offset = shape.size() - this->dimension();
1969 const xexpression_type& e = m_e;
1970 return const_stepper(this, e.stepper_begin(m_e.shape()), offset);
1971 }
1972
1973 template <class CT, class... S>
1974 template <class ST, bool Enable>
1975 inline auto xview<CT, S...>::stepper_end(const ST& shape, layout_type l) const
1976 -> std::enable_if_t<!Enable, const_stepper>
1977 {
1978 size_type offset = shape.size() - this->dimension();
1979 const xexpression_type& e = m_e;
1980 return const_stepper(this, e.stepper_end(m_e.shape(), l), offset, true, l);
1981 }
1982
1983 template <class CT, class... S>
1984 template <class ST, bool Enable>
1985 inline auto xview<CT, S...>::stepper_begin(const ST& shape) -> std::enable_if_t<Enable, stepper>
1986 {
1987 size_type offset = shape.size() - this->dimension();
1988 return stepper(this, data_xbegin(), offset);
1989 }
1990
1991 template <class CT, class... S>
1992 template <class ST, bool Enable>
1993 inline auto xview<CT, S...>::stepper_end(const ST& shape, layout_type l)
1994 -> std::enable_if_t<Enable, stepper>
1995 {
1996 size_type offset = shape.size() - this->dimension();
1997 return stepper(this, data_xend(l, offset), offset);
1998 }
1999
2000 template <class CT, class... S>
2001 template <class ST, bool Enable>
2002 inline auto xview<CT, S...>::stepper_begin(const ST& shape) const
2003 -> std::enable_if_t<Enable, const_stepper>
2004 {
2005 size_type offset = shape.size() - this->dimension();
2006 return const_stepper(this, data_xbegin(), offset);
2007 }
2008
2009 template <class CT, class... S>
2010 template <class ST, bool Enable>
2011 inline auto xview<CT, S...>::stepper_end(const ST& shape, layout_type l) const
2012 -> std::enable_if_t<Enable, const_stepper>
2013 {
2014 size_type offset = shape.size() - this->dimension();
2015 return const_stepper(this, data_xend(l, offset), offset);
2016 }
2017
2018 /********************************
2019 * xview_stepper implementation *
2020 ********************************/
2021
2022 template <bool is_const, class CT, class... S>
2023 inline xview_stepper<is_const, CT, S...>::xview_stepper(
2024 view_type* view,
2025 substepper_type it,
2026 size_type offset,
2027 bool end,
2028 layout_type l
2029 )
2030 : p_view(view)
2031 , m_it(it)
2032 , m_offset(offset)
2033 {
2034 if (!end)
2035 {
2036 std::fill(m_index_keeper.begin(), m_index_keeper.end(), 0);
2037 auto func = [](const auto& s) noexcept
2038 {
2039 return xt::value(s, 0);
2040 };
2041 for (size_type i = 0; i < sizeof...(S); ++i)
2042 {
2043 if (!is_newaxis_slice(i))
2044 {
2045 size_type s = apply<size_type>(i, func, p_view->slices());
2046 size_type index = i - newaxis_count_before<S...>(i);
2047 m_it.step(index, s);
2048 }
2049 }
2050 }
2051 else
2052 {
2053 to_end_impl(l);
2054 }
2055 }
2056
2057 template <bool is_const, class CT, class... S>
2058 inline auto xview_stepper<is_const, CT, S...>::operator*() const -> reference
2059 {
2060 return *m_it;
2061 }
2062
2063 template <bool is_const, class CT, class... S>
2064 inline void xview_stepper<is_const, CT, S...>::step(size_type dim)
2065 {
2066 auto func = [this](size_type index, size_type offset)
2067 {
2068 m_it.step(index, offset);
2069 };
2070 common_step_forward(dim, func);
2071 }
2072
2073 template <bool is_const, class CT, class... S>
2074 inline void xview_stepper<is_const, CT, S...>::step_back(size_type dim)
2075 {
2076 auto func = [this](size_type index, size_type offset)
2077 {
2078 m_it.step_back(index, offset);
2079 };
2080 common_step_backward(dim, func);
2081 }
2082
2083 template <bool is_const, class CT, class... S>
2084 inline void xview_stepper<is_const, CT, S...>::step(size_type dim, size_type n)
2085 {
2086 auto func = [this](size_type index, size_type offset)
2087 {
2088 m_it.step(index, offset);
2089 };
2090 common_step_forward(dim, n, func);
2091 }
2092
2093 template <bool is_const, class CT, class... S>
2094 inline void xview_stepper<is_const, CT, S...>::step_back(size_type dim, size_type n)
2095 {
2096 auto func = [this](size_type index, size_type offset)
2097 {
2098 m_it.step_back(index, offset);
2099 };
2100 common_step_backward(dim, n, func);
2101 }
2102
2103 template <bool is_const, class CT, class... S>
2104 inline void xview_stepper<is_const, CT, S...>::reset(size_type dim)
2105 {
2106 auto func = [this](size_type index, size_type offset)
2107 {
2108 m_it.step_back(index, offset);
2109 };
2110 common_reset(dim, func, false);
2111 }
2112
2113 template <bool is_const, class CT, class... S>
2114 inline void xview_stepper<is_const, CT, S...>::reset_back(size_type dim)
2115 {
2116 auto func = [this](size_type index, size_type offset)
2117 {
2118 m_it.step(index, offset);
2119 };
2120 common_reset(dim, func, true);
2121 }
2122
2123 template <bool is_const, class CT, class... S>
2124 inline void xview_stepper<is_const, CT, S...>::to_begin()
2125 {
2126 std::fill(m_index_keeper.begin(), m_index_keeper.end(), 0);
2127 m_it.to_begin();
2128 }
2129
2130 template <bool is_const, class CT, class... S>
2131 inline void xview_stepper<is_const, CT, S...>::to_end(layout_type l)
2132 {
2133 m_it.to_end(l);
2134 to_end_impl(l);
2135 }
2136
2137 template <bool is_const, class CT, class... S>
2138 inline bool xview_stepper<is_const, CT, S...>::is_newaxis_slice(size_type index) const noexcept
2139 {
2140 // A bit tricky but avoids a lot of template instantiations
2141 return newaxis_count_before<S...>(index + 1) != newaxis_count_before<S...>(index);
2142 }
2143
2144 template <bool is_const, class CT, class... S>
2145 inline void xview_stepper<is_const, CT, S...>::to_end_impl(layout_type l)
2146 {
2147 auto func = [](const auto& s) noexcept
2148 {
2149 return xt::value(s, get_size(s) - 1);
2150 };
2151 auto size_func = [](const auto& s) noexcept
2152 {
2153 return get_size(s);
2154 };
2155
2156 for (size_type i = 0; i < sizeof...(S); ++i)
2157 {
2158 if (!is_newaxis_slice(i))
2159 {
2160 size_type s = apply<size_type>(i, func, p_view->slices());
2161 size_type ix = apply<size_type>(i, size_func, p_view->slices());
2162 m_index_keeper[i] = ix - size_type(1);
2163 size_type index = i - newaxis_count_before<S...>(i);
2164 s = p_view->underlying_size(index) - 1 - s;
2165 m_it.step_back(index, s);
2166 }
2167 }
2168 if (l == layout_type::row_major)
2169 {
2170 for (size_type i = sizeof...(S); i > 0; --i)
2171 {
2172 if (!is_newaxis_slice(i - 1))
2173 {
2174 m_index_keeper[i - 1]++;
2175 break;
2176 }
2177 }
2178 }
2179 else if (l == layout_type::column_major)
2180 {
2181 for (size_type i = 0; i < sizeof...(S); ++i)
2182 {
2183 if (!is_newaxis_slice(i))
2184 {
2185 m_index_keeper[i]++;
2186 break;
2187 }
2188 }
2189 }
2190 else
2191 {
2192 XTENSOR_THROW(std::runtime_error, "Iteration only allowed in row or column major.");
2193 }
2194 }
2195
2196 template <bool is_const, class CT, class... S>
2197 template <class F>
2198 void xview_stepper<is_const, CT, S...>::common_step_forward(size_type dim, F f)
2199 {
2200 if (dim >= m_offset)
2201 {
2202 auto func = [&dim, this](const auto& s) noexcept
2203 {
2204 return step_size(s, this->m_index_keeper[dim]++, 1);
2205 };
2206 size_type index = integral_skip<S...>(dim);
2207 if (!is_newaxis_slice(index))
2208 {
2209 size_type step_size = index < sizeof...(S) ? apply<size_type>(index, func, p_view->slices())
2210 : 1;
2211 index -= newaxis_count_before<S...>(index);
2212 f(index, step_size);
2213 }
2214 }
2215 }
2216
2217 template <bool is_const, class CT, class... S>
2218 template <class F>
2219 void xview_stepper<is_const, CT, S...>::common_step_forward(size_type dim, size_type n, F f)
2220 {
2221 if (dim >= m_offset)
2222 {
2223 auto func = [&dim, &n, this](const auto& s) noexcept
2224 {
2225 auto st_size = step_size(s, this->m_index_keeper[dim], n);
2226 this->m_index_keeper[dim] += n;
2227 return size_type(st_size);
2228 };
2229
2230 size_type index = integral_skip<S...>(dim);
2231 if (!is_newaxis_slice(index))
2232 {
2233 size_type step_size = index < sizeof...(S) ? apply<size_type>(index, func, p_view->slices())
2234 : n;
2235 index -= newaxis_count_before<S...>(index);
2236 f(index, step_size);
2237 }
2238 }
2239 }
2240
2241 template <bool is_const, class CT, class... S>
2242 template <class F>
2243 void xview_stepper<is_const, CT, S...>::common_step_backward(size_type dim, F f)
2244 {
2245 if (dim >= m_offset)
2246 {
2247 auto func = [&dim, this](const auto& s) noexcept
2248 {
2249 this->m_index_keeper[dim]--;
2250 return step_size(s, this->m_index_keeper[dim], 1);
2251 };
2252 size_type index = integral_skip<S...>(dim);
2253 if (!is_newaxis_slice(index))
2254 {
2255 size_type step_size = index < sizeof...(S) ? apply<size_type>(index, func, p_view->slices())
2256 : 1;
2257 index -= newaxis_count_before<S...>(index);
2258 f(index, step_size);
2259 }
2260 }
2261 }
2262
2263 template <bool is_const, class CT, class... S>
2264 template <class F>
2265 void xview_stepper<is_const, CT, S...>::common_step_backward(size_type dim, size_type n, F f)
2266 {
2267 if (dim >= m_offset)
2268 {
2269 auto func = [&dim, &n, this](const auto& s) noexcept
2270 {
2271 this->m_index_keeper[dim] -= n;
2272 return step_size(s, this->m_index_keeper[dim], n);
2273 };
2274
2275 size_type index = integral_skip<S...>(dim);
2276 if (!is_newaxis_slice(index))
2277 {
2278 size_type step_size = index < sizeof...(S) ? apply<size_type>(index, func, p_view->slices())
2279 : n;
2280 index -= newaxis_count_before<S...>(index);
2281 f(index, step_size);
2282 }
2283 }
2284 }
2285
2286 template <bool is_const, class CT, class... S>
2287 template <class F>
2288 void xview_stepper<is_const, CT, S...>::common_reset(size_type dim, F f, bool backwards)
2289 {
2290 auto size_func = [](const auto& s) noexcept
2291 {
2292 return get_size(s);
2293 };
2294 auto end_func = [](const auto& s) noexcept
2295 {
2296 return xt::value(s, get_size(s) - 1) - xt::value(s, 0);
2297 };
2298
2299 size_type index = integral_skip<S...>(dim);
2300 if (!is_newaxis_slice(index))
2301 {
2302 if (dim < m_index_keeper.size())
2303 {
2304 size_type size = index < sizeof...(S) ? apply<size_type>(index, size_func, p_view->slices())
2305 : p_view->shape()[dim];
2306 m_index_keeper[dim] = backwards ? size - 1 : 0;
2307 }
2308
2309 size_type reset_n = index < sizeof...(S) ? apply<size_type>(index, end_func, p_view->slices())
2310 : p_view->shape()[dim] - 1;
2311 index -= newaxis_count_before<S...>(index);
2312 f(index, reset_n);
2313 }
2314 }
2315}
2316
2317#endif
Fixed shape implementation for compile time defined arrays.
Base class for implementation of common expression access methods.
size_type shape(size_type index) const
Returns the i-th dimension of the expression.
Base class for multidimensional iterable expressions.
Implementation of the xsemantic_base interface for multidimensional views.
Multidimensional view with tensor semantic.
Definition xview.hpp:360
xview(CTA &&e, FSL &&first_slice, SL &&... slices) noexcept
Constructs a view on the specified xexpression.
Definition xview.hpp:881
const slice_type & slices() const noexcept
Returns the slices of the view.
Definition xview.hpp:965
bool has_linear_assign(const ST &strides) const
Checks whether the xview can be linearly assigned to an expression with the specified strides.
Definition xview.hpp:1410
const inner_shape_type & shape() const noexcept
Returns the shape of the view.
Definition xview.hpp:956
bool broadcast_shape(ST &shape, bool reuse_cache=false) const
Broadcast the shape of the view to the specified parameter.
Definition xview.hpp:1398
xexpression_type & expression() noexcept
Returns a reference to the underlying expression of the view.
Definition xview.hpp:1145
void fill(const T &value)
Fills the view with the given value.
Definition xview.hpp:1021
layout_type layout() const noexcept
Returns the slices of the view.
Definition xview.hpp:974
auto arg(E &&e) noexcept
Calculates the phase angle (in radians) elementwise for the complex numbers in e.
Definition xcomplex.hpp:221
auto squeeze(E &&e)
Returns a squeeze view of the given expression.
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
auto all() noexcept
Returns a slice representing a full dimension, to be used as an argument of view function.
Definition xslice.hpp:234
auto row(E &&e, std::ptrdiff_t index)
Constructs and returns a row (sliced view) on the specified expression.
Definition xview.hpp:1922
layout_type
Definition xlayout.hpp:24
auto col(E &&e, std::ptrdiff_t index)
Constructs and returns a column (sliced view) on the specified expression.
Definition xview.hpp:1937
auto view(E &&e, S &&... slices)
Constructs and returns a view on the specified xexpression.
Definition xview.hpp:1834