xtensor
Loading...
Searching...
No Matches
xfunctor_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_FUNCTOR_VIEW_HPP
11#define XTENSOR_FUNCTOR_VIEW_HPP
12
13#include <algorithm>
14#include <array>
15#include <cstddef>
16#include <type_traits>
17#include <utility>
18
19#include <xtl/xproxy_wrapper.hpp>
20
21#include "xaccessible.hpp"
22#include "xarray.hpp"
23#include "xexpression.hpp"
24#include "xiterator.hpp"
25#include "xsemantic.hpp"
26#include "xtensor.hpp"
27#include "xutils.hpp"
28
29namespace xt
30{
38 /************************************************
39 * xfunctor_view and xfunctor_adaptor extension *
40 ************************************************/
41
42 namespace extension
43 {
44 template <class Tag, class F, class CT>
46
47 template <class F, class CT>
52
53 template <class F, class CT>
54 struct xfunctor_view_base : xfunctor_view_base_impl<xexpression_tag_t<CT>, F, CT>
55 {
56 };
57
58 template <class F, class CT>
59 using xfunctor_view_base_t = typename xfunctor_view_base<F, CT>::type;
60 }
61
62 /*************************************
63 * xfunctor_applier_base declaration *
64 *************************************/
65
66 template <class F, class IT>
68
69 template <class F, class ST>
70 class xfunctor_stepper;
71
72 template <class D>
74 {
75 public:
76
79 using xexpression_type = typename inner_types::xexpression_type;
80 using undecay_expression = typename inner_types::undecay_expression;
81 using functor_type = typename inner_types::functor_type;
83
84 using extension_base = extension::xfunctor_view_base_t<functor_type, undecay_expression>;
85 using expression_tag = typename extension_base::expression_tag;
86
87 using value_type = typename functor_type::value_type;
88 using reference = typename inner_types::reference;
89 using const_reference = typename inner_types::const_reference;
90 using pointer = typename functor_type::pointer;
91 using const_pointer = typename functor_type::const_pointer;
92 using size_type = typename inner_types::size_type;
93 using difference_type = typename xexpression_type::difference_type;
94
95 using shape_type = typename xexpression_type::shape_type;
96 using strides_type = xtl::mpl::eval_if_t<
98 detail::expr_strides_type<xexpression_type>,
100 using backstrides_type = xtl::mpl::eval_if_t<
102 detail::expr_backstrides_type<xexpression_type>,
104
105 using inner_shape_type = typename xexpression_type::inner_shape_type;
106 using inner_strides_type = xtl::mpl::eval_if_t<
108 detail::expr_inner_strides_type<xexpression_type>,
110 using inner_backstrides_type = xtl::mpl::eval_if_t<
112 detail::expr_inner_backstrides_type<xexpression_type>,
114
116
117 static constexpr layout_type static_layout = xexpression_type::static_layout;
118 static constexpr bool contiguous_layout = xexpression_type::contiguous_layout;
119
122
123 template <layout_type L>
125 template <layout_type L>
127 const functor_type,
128 typename xexpression_type::template const_layout_iterator<L>>;
129
130 template <layout_type L>
132 functor_type,
133 typename xexpression_type::template reverse_layout_iterator<L>>;
134 template <layout_type L>
136 const functor_type,
137 typename xexpression_type::template const_reverse_layout_iterator<L>>;
138
139 template <class S, layout_type L>
141 template <class S, layout_type L>
143 functor_type,
145
146 template <class S, layout_type L>
148 functor_type,
149 typename xexpression_type::template reverse_broadcast_iterator<S, L>>;
150 template <class S, layout_type L>
152 functor_type,
153 typename xexpression_type::template const_reverse_broadcast_iterator<S, L>>;
154
159 const functor_type,
160 typename xexpression_type::const_reverse_linear_iterator>;
161
166
167 explicit xfunctor_applier_base(undecay_expression) noexcept;
168
169 template <class Func, class E>
171
172 size_type size() const noexcept;
173 const inner_shape_type& shape() const noexcept;
174 const inner_strides_type& strides() const noexcept;
175 const inner_backstrides_type& backstrides() const noexcept;
178
180 bool is_contiguous() const noexcept;
181
182 template <class... Args>
183 reference operator()(Args... args);
184
185 template <class... Args>
186 reference unchecked(Args... args);
187
189 reference element(IT first, IT last);
190
191 template <class... Args>
192 const_reference operator()(Args... args) const;
193
194 template <class... Args>
195 const_reference unchecked(Args... args) const;
196
198 const_reference element(IT first, IT last) const;
199
204 using accessible_base::periodic;
205
207
208 xexpression_type& expression() noexcept;
209 const xexpression_type& expression() const noexcept;
210
213
216
217 template <class FCT = functor_type>
218 auto data_element(size_type i)
219 -> decltype(std::declval<FCT>()(std::declval<undecay_expression>().data_element(i)))
220 {
221 return m_functor(m_e.data_element(i));
222 }
223
224 template <class FCT = functor_type>
225 auto data_element(size_type i) const
226 -> decltype(std::declval<FCT>()(std::declval<const undecay_expression>().data_element(i)))
227 {
228 return m_functor(m_e.data_element(i));
229 }
230
231 template <class FCT = functor_type>
232 auto flat(size_type i) -> decltype(std::declval<FCT>()(std::declval<undecay_expression>().flat(i)))
233 {
234 return m_functor(m_e.flat(i));
235 }
236
237 template <class FCT = functor_type>
238 auto flat(size_type i) const
239 -> decltype(std::declval<FCT>()(std::declval<const undecay_expression>().flat(i)))
240 {
241 return m_functor(m_e.flat(i));
242 }
243
244 // The following functions are defined inline because otherwise signatures
245 // don't match on GCC.
246 template <
247 class align,
248 class requested_type = typename xexpression_type::value_type,
250 class FCT = functor_type>
251 auto load_simd(size_type i) const
252 -> decltype(std::declval<FCT>().template proxy_simd_load<align, requested_type, N>(
253 std::declval<undecay_expression>(),
254 i
255 ))
256 {
257 return m_functor.template proxy_simd_load<align, requested_type, N>(m_e, i);
258 }
259
260 template <class align, class simd, class FCT = functor_type>
261 auto store_simd(size_type i, const simd& e)
262 -> decltype(std::declval<FCT>()
263 .template proxy_simd_store<align>(std::declval<undecay_expression>(), i, e))
264 {
265 return m_functor.template proxy_simd_store<align>(m_e, i, e);
266 }
267
268 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
270 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
272
273 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
275 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
277 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
279 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
281
282 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
284 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
286
287 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
289 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
291 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
293 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
295
296 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
298 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
300
301 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
303 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
305 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
307 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
309
310 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
312 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
314
315 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
317 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
319 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
321 template <class S, layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
323
324 linear_iterator linear_begin() noexcept;
325 linear_iterator linear_end() noexcept;
326
327 const_linear_iterator linear_begin() const noexcept;
329 const_linear_iterator linear_cbegin() const noexcept;
331
332 reverse_linear_iterator linear_rbegin() noexcept;
333 reverse_linear_iterator linear_rend() noexcept;
334
339
341 stepper stepper_begin(const S& shape) noexcept;
343 stepper stepper_end(const S& shape, layout_type l) noexcept;
345 const_stepper stepper_begin(const S& shape) const noexcept;
348
349 protected:
350
351 undecay_expression m_e;
352 functor_type m_functor;
353
354 private:
355
358 };
359
360 template <class D, class T>
362 : xtl::conjunction<
363 has_simd_type<T>,
365 detail::has_simd_interface_impl<xfunctor_applier_base<D>, T>>
366 {
367 };
368
369 /********************************
370 * xfunctor_view_temporary_type *
371 ********************************/
372
373 namespace detail
374 {
375 // TODO replace with xexpression_for_shape ...
376 template <class F, class S, layout_type L>
377 struct functorview_temporary_type_impl
378 {
380 };
381
382 template <class F, class T, std::size_t N, layout_type L>
383 struct functorview_temporary_type_impl<F, std::array<T, N>, L>
384 {
385 using type = xtensor<typename F::value_type, N, L>;
386 };
387 }
388
389 template <class F, class E>
394
395 /*****************************
396 * xfunctor_view declaration *
397 *****************************/
398
399 template <class F, class CT>
400 class xfunctor_view;
401
402 template <class F, class CT>
404 {
405 using xexpression_type = std::decay_t<CT>;
406 using undecay_expression = CT;
407 using functor_type = std::decay_t<F>;
408 using reference = decltype(std::declval<F>()(std::declval<xexpression_type>()()));
409 using const_reference = decltype(std::declval<F>()(std::declval<const xexpression_type>()()));
410 using size_type = typename xexpression_type::size_type;
411 using temporary_type = typename xfunctor_view_temporary_type<F, xexpression_type>::type;
412 };
413
414 template <class F, class CT, class T>
416 : has_simd_interface<xfunctor_applier_base<xfunctor_view<F, CT>>, T>
417 {
418 };
419
439 template <class F, class CT>
440 class xfunctor_view : public xfunctor_applier_base<xfunctor_view<F, CT>>,
441 public xview_semantic<xfunctor_view<F, CT>>,
442 public extension::xfunctor_view_base_t<F, CT>
443 {
444 public:
445
448
449 // constructors
450 using xfunctor_applier_base<self_type>::xfunctor_applier_base;
451
452 template <class E>
453 self_type& operator=(const xexpression<E>& e);
454
455 template <class E>
456 disable_xexpression<E, self_type>& operator=(const E& e);
457
458 template <class E>
460
461 template <class E>
462 rebind_t<E> build_functor_view(E&& e) const;
463
464 private:
465
466 using temporary_type = typename xcontainer_inner_types<self_type>::temporary_type;
467 void assign_temporary_impl(temporary_type&& tmp);
468 friend class xview_semantic<self_type>;
469 friend class xaccessible<self_type>;
470 };
471
472 /********************************
473 * xfunctor_adaptor declaration *
474 ********************************/
475
476 template <class F, class CT>
477 class xfunctor_adaptor;
478
479 template <class F, class CT>
481 {
482 using xexpression_type = std::decay_t<CT>;
483 using undecay_expression = CT;
484 using functor_type = std::decay_t<F>;
485 using reference = typename functor_type::reference;
486 using const_reference = typename functor_type::const_reference;
487 using size_type = typename xexpression_type::size_type;
488 using temporary_type = typename xfunctor_view_temporary_type<F, xexpression_type>::type;
489 };
490
491 template <class F, class CT, class T>
493 : has_simd_interface<xfunctor_applier_base<xfunctor_adaptor<F, CT>>, T>
494 {
495 };
496
508 template <class F, class CT>
509 class xfunctor_adaptor : public xfunctor_applier_base<xfunctor_adaptor<F, CT>>,
510 public xcontainer_semantic<xfunctor_adaptor<F, CT>>,
511 public extension::xfunctor_view_base_t<F, CT>
512 {
513 public:
514
517 using xexpression_type = std::decay_t<CT>;
519 using shape_type = typename base_type::shape_type;
520 using strides_type = typename xexpression_type::strides_type;
521 // constructors
522 using xfunctor_applier_base<self_type>::xfunctor_applier_base;
523
524 template <class E>
525 self_type& operator=(const xexpression<E>& e);
526
527 template <class E>
528 disable_xexpression<E, self_type>& operator=(const E& e);
529
530 template <class S = shape_type>
531 auto resize(S&& shape, bool force = false);
532
533 template <class S = shape_type>
534 auto resize(S&& shape, layout_type l);
535
536 template <class S = shape_type>
537 auto resize(S&& shape, const strides_type& strides);
538
539 template <class S = shape_type>
540 auto& reshape(S&& shape, layout_type layout = base_type::static_layout) &;
541
542 private:
543
544 using temporary_type = typename xcontainer_inner_types<self_type>::temporary_type;
545 void assign_temporary_impl(temporary_type&& tmp);
546 friend class xcontainer_semantic<self_type>;
547 friend class xaccessible<self_type>;
548 };
549
550 /*********************************
551 * xfunctor_iterator declaration *
552 *********************************/
553
554 template <class R>
556 {
557 using reference = R;
558 using pointer = std::add_pointer_t<std::remove_reference_t<R>>;
559 };
560
561 namespace detail
562 {
563 template <class F, class IT>
564 struct xfunctor_invoker
565 {
566 using type = decltype(std::declval<F>()(*(std::declval<IT>())));
567 };
568
569 template <class F, class IT>
570 using xfunctor_invoker_t = typename xfunctor_invoker<F, IT>::type;
571 }
572
573 template <class F, class IT>
574 class xfunctor_iterator : public xtl::xrandom_access_iterator_base<
575 xfunctor_iterator<F, IT>,
576 typename std::decay_t<F>::value_type,
577 typename std::iterator_traits<IT>::difference_type,
578 typename xproxy_inner_types<detail::xfunctor_invoker_t<F, IT>>::pointer,
579 typename xproxy_inner_types<detail::xfunctor_invoker_t<F, IT>>::reference>
580 {
581 public:
582
583 using functor_type = F;
584 using subiterator_traits = std::iterator_traits<IT>;
585
587 using value_type = typename functor_type::value_type;
588 using reference = typename proxy_inner::reference;
589 using pointer = typename proxy_inner::pointer;
590 using difference_type = typename subiterator_traits::difference_type;
591 using iterator_category = typename subiterator_traits::iterator_category;
592
594
595 xfunctor_iterator(const IT&, functor_type*);
596
597 self_type& operator++();
598 self_type& operator--();
599
600 self_type& operator+=(difference_type n);
601 self_type& operator-=(difference_type n);
602
603 difference_type operator-(xfunctor_iterator rhs) const;
604
605 reference operator*() const;
606 pointer operator->() const;
607
608 bool equal(const xfunctor_iterator& rhs) const;
609 bool less_than(const xfunctor_iterator& rhs) const;
610
611 private:
612
613 IT m_it;
614 functor_type* p_functor;
615 };
616
617 template <class F, class IT>
619
620 template <class F, class IT>
622
623 /********************************
624 * xfunctor_stepper declaration *
625 ********************************/
626
627 template <class F, class ST>
629 {
630 public:
631
632 using functor_type = F;
633
635 using value_type = typename functor_type::value_type;
636 using reference = typename proxy_inner::reference;
637 using pointer = std::remove_reference_t<reference>*;
638 using size_type = typename ST::size_type;
639 using difference_type = typename ST::difference_type;
640
641 using shape_type = typename ST::shape_type;
642
643 xfunctor_stepper() = default;
644 xfunctor_stepper(const ST&, functor_type*);
645
646 reference operator*() const;
647
648 void step(size_type dim);
649 void step_back(size_type dim);
650 void step(size_type dim, size_type n);
651 void step_back(size_type dim, size_type n);
652 void reset(size_type dim);
653 void reset_back(size_type dim);
654
655 void to_begin();
656 void to_end(layout_type);
657
658 private:
659
660 ST m_stepper;
661 functor_type* p_functor;
662 };
663
664 /****************************************
665 * xfunctor_applier_base implementation *
666 ****************************************/
667
672
678 template <class D>
680 : m_e(e)
681 , m_functor(functor_type())
682 {
683 }
684
691 template <class D>
692 template <class Func, class E>
694 : m_e(std::forward<E>(e))
695 , m_functor(std::forward<Func>(func))
696 {
697 }
698
700
708 template <class D>
710 {
711 return m_e.size();
712 }
713
717 template <class D>
718 inline auto xfunctor_applier_base<D>::shape() const noexcept -> const inner_shape_type&
719 {
720 return m_e.shape();
721 }
722
726 template <class D>
727 inline auto xfunctor_applier_base<D>::strides() const noexcept -> const inner_strides_type&
728 {
729 return m_e.strides();
730 }
731
735 template <class D>
736 inline auto xfunctor_applier_base<D>::backstrides() const noexcept -> const inner_backstrides_type&
737 {
738 return m_e.backstrides();
739 }
740
744 template <class D>
746 {
747 return m_e.layout();
748 }
749
750 template <class D>
752 {
753 return m_e.is_contiguous();
754 }
755
757
768 template <class D>
769 template <class... Args>
770 inline auto xfunctor_applier_base<D>::operator()(Args... args) -> reference
771 {
772 XTENSOR_TRY(check_index(shape(), args...));
773 XTENSOR_CHECK_DIMENSION(shape(), args...);
774 return m_functor(m_e(args...));
775 }
776
796 template <class D>
797 template <class... Args>
798 inline auto xfunctor_applier_base<D>::unchecked(Args... args) -> reference
799 {
800 return m_functor(m_e.unchecked(args...));
801 }
802
810 template <class D>
811 template <class IT>
813 {
814 XTENSOR_TRY(check_element_index(shape(), first, last));
815 return m_functor(m_e.element(first, last));
816 }
817
824 template <class D>
825 template <class... Args>
826 inline auto xfunctor_applier_base<D>::operator()(Args... args) const -> const_reference
827 {
828 XTENSOR_TRY(check_index(shape(), args...));
829 XTENSOR_CHECK_DIMENSION(shape(), args...);
830 return m_functor(m_e(args...));
831 }
832
852 template <class D>
853 template <class... Args>
854 inline auto xfunctor_applier_base<D>::unchecked(Args... args) const -> const_reference
855 {
856 return m_functor(m_e.unchecked(args...));
857 }
858
866 template <class D>
867 template <class IT>
868 inline auto xfunctor_applier_base<D>::element(IT first, IT last) const -> const_reference
869 {
870 XTENSOR_TRY(check_element_index(shape(), first, last));
871 return m_functor(m_e.element(first, last));
872 }
873
877 template <class D>
878 inline auto xfunctor_applier_base<D>::expression() noexcept -> xexpression_type&
879 {
880 return m_e;
881 }
882
886 template <class D>
887 inline auto xfunctor_applier_base<D>::expression() const noexcept -> const xexpression_type&
888 {
889 return m_e;
890 }
891
893
904 template <class D>
905 template <class S>
907 {
908 return m_e.broadcast_shape(shape, reuse_cache);
909 }
910
917 template <class D>
918 template <class S>
920 {
921 return m_e.has_linear_assign(strides);
922 }
923
925
934 template <class D>
935 template <layout_type L>
937 {
938 return xfunctor_iterator<functor_type, decltype(m_e.template begin<L>())>(
939 m_e.template begin<L>(),
940 &m_functor
941 );
942 }
943
949 template <class D>
950 template <layout_type L>
952 {
953 return xfunctor_iterator<functor_type, decltype(m_e.template end<L>())>(m_e.template end<L>(), &m_functor);
954 }
955
960 template <class D>
961 template <layout_type L>
963 {
964 return this->template cbegin<L>();
965 }
966
972 template <class D>
973 template <layout_type L>
975 {
976 return this->template cend<L>();
977 }
978
983 template <class D>
984 template <layout_type L>
986 {
987 return xfunctor_iterator<const functor_type, decltype(m_e.template cbegin<L>())>(
988 m_e.template cbegin<L>(),
989 &m_functor
990 );
991 }
992
998 template <class D>
999 template <layout_type L>
1001 {
1002 return xfunctor_iterator<const functor_type, decltype(m_e.template cend<L>())>(
1003 m_e.template cend<L>(),
1004 &m_functor
1005 );
1006 }
1007
1009
1021 template <class D>
1022 template <class S, layout_type L>
1024 {
1025 return broadcast_iterator<S, L>(m_e.template begin<S, L>(shape), &m_functor);
1026 }
1027
1035 template <class D>
1036 template <class S, layout_type L>
1038 {
1039 return broadcast_iterator<S, L>(m_e.template end<S, L>(shape), &m_functor);
1040 }
1041
1049 template <class D>
1050 template <class S, layout_type L>
1051 inline auto xfunctor_applier_base<D>::begin(const S& shape) const noexcept
1053 {
1054 return cbegin<S, L>(shape);
1055 }
1056
1064 template <class D>
1065 template <class S, layout_type L>
1067 {
1068 return cend<S, L>(shape);
1069 }
1070
1078 template <class D>
1079 template <class S, layout_type L>
1080 inline auto xfunctor_applier_base<D>::cbegin(const S& shape) const noexcept
1082 {
1083 return const_broadcast_iterator<S, L>(m_e.template cbegin<S, L>(shape), &m_functor);
1084 }
1085
1093 template <class D>
1094 template <class S, layout_type L>
1096 {
1097 return const_broadcast_iterator<S, L>(m_e.template cend<S, L>(shape), &m_functor);
1098 }
1099
1101
1110 template <class D>
1111 template <layout_type L>
1113 {
1114 return xfunctor_iterator<functor_type, decltype(m_e.template rbegin<L>())>(
1115 m_e.template rbegin<L>(),
1116 &m_functor
1117 );
1118 }
1119
1125 template <class D>
1126 template <layout_type L>
1128 {
1129 return xfunctor_iterator<functor_type, decltype(m_e.template rend<L>())>(
1130 m_e.template rend<L>(),
1131 &m_functor
1132 );
1133 }
1134
1139 template <class D>
1140 template <layout_type L>
1142 {
1143 return this->template crbegin<L>();
1144 }
1145
1151 template <class D>
1152 template <layout_type L>
1154 {
1155 return this->template crend<L>();
1156 }
1157
1162 template <class D>
1163 template <layout_type L>
1165 {
1166 return xfunctor_iterator<const functor_type, decltype(m_e.template crbegin<L>())>(
1167 m_e.template crbegin<L>(),
1168 &m_functor
1169 );
1170 }
1171
1177 template <class D>
1178 template <layout_type L>
1180 {
1181 return xfunctor_iterator<const functor_type, decltype(m_e.template crend<L>())>(
1182 m_e.template crend<L>(),
1183 &m_functor
1184 );
1185 }
1186
1188
1200 template <class D>
1201 template <class S, layout_type L>
1203 {
1204 return reverse_broadcast_iterator<S, L>(m_e.template rbegin<S, L>(shape), &m_functor);
1205 }
1206
1214 template <class D>
1215 template <class S, layout_type L>
1217 {
1218 return reverse_broadcast_iterator<S, L>(m_e.template rend<S, L>(shape), &m_functor);
1219 }
1220
1228 template <class D>
1229 template <class S, layout_type L>
1230 inline auto xfunctor_applier_base<D>::rbegin(const S& shape) const noexcept
1232 {
1233 return crbegin<S, L>(shape);
1234 }
1235
1243 template <class D>
1244 template <class S, layout_type L>
1245 inline auto xfunctor_applier_base<D>::rend(const S& /*shape*/) const noexcept
1247 {
1248 return crend<S, L>();
1249 }
1250
1258 template <class D>
1259 template <class S, layout_type L>
1260 inline auto xfunctor_applier_base<D>::crbegin(const S& /*shape*/) const noexcept
1262 {
1263 return const_reverse_broadcast_iterator<S, L>(m_e.template crbegin<S, L>(), &m_functor);
1264 }
1265
1273 template <class D>
1274 template <class S, layout_type L>
1275 inline auto xfunctor_applier_base<D>::crend(const S& shape) const noexcept
1277 {
1278 return const_reverse_broadcast_iterator<S, L>(m_e.template crend<S, L>(shape), &m_functor);
1279 }
1280
1282
1283 template <class D>
1284 inline auto xfunctor_applier_base<D>::linear_begin() noexcept -> linear_iterator
1285 {
1286 return linear_iterator(m_e.linear_begin(), &m_functor);
1287 }
1288
1289 template <class D>
1290 inline auto xfunctor_applier_base<D>::linear_end() noexcept -> linear_iterator
1291 {
1292 return linear_iterator(m_e.linear_end(), &m_functor);
1293 }
1294
1295 template <class D>
1296 inline auto xfunctor_applier_base<D>::linear_begin() const noexcept -> const_linear_iterator
1297 {
1298 return const_linear_iterator(m_e.linear_begin(), &m_functor);
1299 }
1300
1301 template <class D>
1302 inline auto xfunctor_applier_base<D>::linear_end() const noexcept -> const_linear_iterator
1303 {
1304 return const_linear_iterator(m_e.linear_end(), &m_functor);
1305 }
1306
1307 template <class D>
1308 inline auto xfunctor_applier_base<D>::linear_cbegin() const noexcept -> const_linear_iterator
1309 {
1310 return const_linear_iterator(m_e.linear_cbegin(), &m_functor);
1311 }
1312
1313 template <class D>
1314 inline auto xfunctor_applier_base<D>::linear_cend() const noexcept -> const_linear_iterator
1315 {
1316 return const_linear_iterator(m_e.linear_cend(), &m_functor);
1317 }
1318
1319 template <class D>
1320 inline auto xfunctor_applier_base<D>::linear_rbegin() noexcept -> reverse_linear_iterator
1321 {
1322 return reverse_linear_iterator(m_e.linear_rbegin(), &m_functor);
1323 }
1324
1325 template <class D>
1326 inline auto xfunctor_applier_base<D>::linear_rend() noexcept -> reverse_linear_iterator
1327 {
1328 return reverse_linear_iterator(m_e.linear_rend(), &m_functor);
1329 }
1330
1331 template <class D>
1332 inline auto xfunctor_applier_base<D>::linear_rbegin() const noexcept -> const_reverse_linear_iterator
1333 {
1334 return const_reverse_linear_iterator(m_e.linear_rbegin(), &m_functor);
1335 }
1336
1337 template <class D>
1338 inline auto xfunctor_applier_base<D>::linear_rend() const noexcept -> const_reverse_linear_iterator
1339 {
1340 return const_reverse_linear_iterator(m_e.linear_rend(), &m_functor);
1341 }
1342
1343 template <class D>
1344 inline auto xfunctor_applier_base<D>::linear_crbegin() const noexcept -> const_reverse_linear_iterator
1345 {
1346 return const_reverse_linear_iterator(m_e.linear_crbegin(), &m_functor);
1347 }
1348
1349 template <class D>
1350 inline auto xfunctor_applier_base<D>::linear_crend() const noexcept -> const_reverse_linear_iterator
1351 {
1352 return const_reverse_linear_iterator(m_e.linear_crend(), &m_functor);
1353 }
1354
1355 /***************
1356 * stepper api *
1357 ***************/
1358
1359 template <class D>
1360 template <class S>
1361 inline auto xfunctor_applier_base<D>::stepper_begin(const S& shape) noexcept -> stepper
1362 {
1363 return stepper(m_e.stepper_begin(shape), &m_functor);
1364 }
1365
1366 template <class D>
1367 template <class S>
1368 inline auto xfunctor_applier_base<D>::stepper_end(const S& shape, layout_type l) noexcept -> stepper
1369 {
1370 return stepper(m_e.stepper_end(shape, l), &m_functor);
1371 }
1372
1373 template <class D>
1374 template <class S>
1375 inline auto xfunctor_applier_base<D>::stepper_begin(const S& shape) const noexcept -> const_stepper
1376 {
1377 const xexpression_type& const_m_e = m_e;
1378 return const_stepper(const_m_e.stepper_begin(shape), &m_functor);
1379 }
1380
1381 template <class D>
1382 template <class S>
1383 inline auto xfunctor_applier_base<D>::stepper_end(const S& shape, layout_type l) const noexcept
1384 -> const_stepper
1385 {
1386 const xexpression_type& const_m_e = m_e;
1387 return const_stepper(const_m_e.stepper_end(shape, l), &m_functor);
1388 }
1389
1390 /********************************
1391 * xfunctor_view implementation *
1392 ********************************/
1393
1401 template <class F, class CT>
1402 template <class E>
1404 {
1405 bool cond = (e.derived_cast().shape().size() == this->dimension())
1406 && std::equal(this->shape().begin(), this->shape().end(), e.derived_cast().shape().begin());
1407 if (!cond)
1408 {
1409 semantic_base::operator=(broadcast(e.derived_cast(), this->shape()));
1410 }
1411 else
1412 {
1413 semantic_base::operator=(e);
1414 }
1415 return *this;
1416 }
1417
1419
1420 template <class F, class CT>
1421 template <class E>
1423 {
1424 std::fill(this->begin(), this->end(), e);
1425 return *this;
1426 }
1427
1428 template <class F, class CT>
1429 inline void xfunctor_view<F, CT>::assign_temporary_impl(temporary_type&& tmp)
1430 {
1431 std::copy(tmp.cbegin(), tmp.cend(), this->begin());
1432 }
1433
1434 template <class F, class CT>
1435 template <class E>
1436 inline auto xfunctor_view<F, CT>::build_functor_view(E&& e) const -> rebind_t<E>
1437 {
1438 return rebind_t<E>((this->m_functor), std::forward<E>(e));
1439 }
1440
1441 /***********************************
1442 * xfunctor_adaptor implementation *
1443 ***********************************/
1444
1452 template <class F, class CT>
1453 template <class E>
1455 {
1456 const auto& de = e.derived_cast();
1457 this->m_e.resize(de.shape());
1458
1459 if (this->layout() == de.layout())
1460 {
1461 std::copy(de.linear_begin(), de.linear_end(), this->linear_begin());
1462 }
1463 else
1464 {
1465 // note: does this even select the current layout of *this* for iteration?
1466 std::copy(de.begin(), de.end(), this->begin());
1467 }
1468
1469 return *this;
1470 }
1471
1473
1474 template <class F, class CT>
1475 template <class S>
1477 {
1478 this->m_e.resize(std::forward<S>(shape), force);
1479 }
1480
1481 template <class F, class CT>
1482 template <class S>
1483 auto xfunctor_adaptor<F, CT>::resize(S&& shape, layout_type l)
1484 {
1485 this->m_e.resize(std::forward<S>(shape), l);
1486 }
1487
1488 template <class F, class CT>
1489 template <class S>
1490 auto xfunctor_adaptor<F, CT>::resize(S&& shape, const strides_type& strides)
1491 {
1492 this->m_e.resize(std::forward<S>(shape), strides);
1493 }
1494
1495 template <class F, class CT>
1496 template <class S>
1497 auto& xfunctor_adaptor<F, CT>::reshape(S&& shape, layout_type layout) &
1498 {
1499 this->m_e.reshape(std::forward<S>(shape), layout);
1500 return *this;
1501 }
1502
1503 /************************************
1504 * xfunctor_iterator implementation *
1505 ************************************/
1506
1507 template <class F, class IT>
1508 xfunctor_iterator<F, IT>::xfunctor_iterator(const IT& it, functor_type* pf)
1509 : m_it(it)
1510 , p_functor(pf)
1511 {
1512 }
1513
1514 template <class F, class IT>
1515 inline auto xfunctor_iterator<F, IT>::operator++() -> self_type&
1516 {
1517 ++m_it;
1518 return *this;
1519 }
1520
1521 template <class F, class IT>
1522 inline auto xfunctor_iterator<F, IT>::operator--() -> self_type&
1523 {
1524 --m_it;
1525 return *this;
1526 }
1527
1528 template <class F, class IT>
1529 inline auto xfunctor_iterator<F, IT>::operator+=(difference_type n) -> self_type&
1530 {
1531 m_it += n;
1532 return *this;
1533 }
1534
1535 template <class F, class IT>
1536 inline auto xfunctor_iterator<F, IT>::operator-=(difference_type n) -> self_type&
1537 {
1538 m_it -= n;
1539 return *this;
1540 }
1541
1542 template <class F, class IT>
1543 inline auto xfunctor_iterator<F, IT>::operator-(xfunctor_iterator rhs) const -> difference_type
1544 {
1545 return m_it - rhs.m_it;
1546 }
1547
1548 template <class F, class IT>
1549 auto xfunctor_iterator<F, IT>::operator*() const -> reference
1550 {
1551 return (*p_functor)(*m_it);
1552 }
1553
1554 template <class F, class IT>
1555 auto xfunctor_iterator<F, IT>::operator->() const -> pointer
1556 {
1557 return &(operator*());
1558 }
1559
1560 template <class F, class IT>
1561 auto xfunctor_iterator<F, IT>::equal(const xfunctor_iterator& rhs) const -> bool
1562 {
1563 return m_it == rhs.m_it;
1564 }
1565
1566 template <class F, class IT>
1567 auto xfunctor_iterator<F, IT>::less_than(const xfunctor_iterator& rhs) const -> bool
1568 {
1569 return m_it < rhs.m_it;
1570 }
1571
1572 template <class F, class IT>
1573 bool operator==(const xfunctor_iterator<F, IT>& lhs, const xfunctor_iterator<F, IT>& rhs)
1574 {
1575 return lhs.equal(rhs);
1576 }
1577
1578 template <class F, class IT>
1579 bool operator<(const xfunctor_iterator<F, IT>& lhs, const xfunctor_iterator<F, IT>& rhs)
1580 {
1581 return !lhs.less_than(rhs);
1582 }
1583
1584 /***********************************
1585 * xfunctor_stepper implementation *
1586 ***********************************/
1587
1588 template <class F, class ST>
1589 xfunctor_stepper<F, ST>::xfunctor_stepper(const ST& stepper, functor_type* pf)
1590 : m_stepper(stepper)
1591 , p_functor(pf)
1592 {
1593 }
1594
1595 template <class F, class ST>
1596 auto xfunctor_stepper<F, ST>::operator*() const -> reference
1597 {
1598 return (*p_functor)(*m_stepper);
1599 }
1600
1601 template <class F, class ST>
1602 void xfunctor_stepper<F, ST>::step(size_type dim)
1603 {
1604 m_stepper.step(dim);
1605 }
1606
1607 template <class F, class ST>
1608 void xfunctor_stepper<F, ST>::step_back(size_type dim)
1609 {
1610 m_stepper.step_back(dim);
1611 }
1612
1613 template <class F, class ST>
1614 void xfunctor_stepper<F, ST>::step(size_type dim, size_type n)
1615 {
1616 m_stepper.step(dim, n);
1617 }
1618
1619 template <class F, class ST>
1620 void xfunctor_stepper<F, ST>::step_back(size_type dim, size_type n)
1621 {
1622 m_stepper.step_back(dim, n);
1623 }
1624
1625 template <class F, class ST>
1626 void xfunctor_stepper<F, ST>::reset(size_type dim)
1627 {
1628 m_stepper.reset(dim);
1629 }
1630
1631 template <class F, class ST>
1632 void xfunctor_stepper<F, ST>::reset_back(size_type dim)
1633 {
1634 m_stepper.reset_back(dim);
1635 }
1636
1637 template <class F, class ST>
1638 void xfunctor_stepper<F, ST>::to_begin()
1639 {
1640 m_stepper.to_begin();
1641 }
1642
1643 template <class F, class ST>
1644 void xfunctor_stepper<F, ST>::to_end(layout_type l)
1645 {
1646 m_stepper.to_end(l);
1647 }
1648}
1649#endif
Base class for implementation of common expression access methods.
Base class for implementation of common expression constant access methods.
size_type dimension() const noexcept
Returns the number of dimensions of the expression.
bool in_bounds(Args... args) const
Returns true only if the the specified position is a valid entry in the expression.
Implementation of the xsemantic_base interface for dense multidimensional containers.
Adapt a container with a functor, forwarding methods such as resize / reshape.
auto end() noexcept
Returns an iterator to the element following the last element of the expression.
const inner_backstrides_type & backstrides() const noexcept
Returns the backstrides of the expression.
layout_type layout() const noexcept
Returns the layout_type of the expression.
xfunctor_applier_base(undecay_expression) noexcept
Constructs an xfunctor_applier_base expression wrappering the specified xt::xexpression.
xexpression_type & expression() noexcept
Returns a reference to the underlying expression of the view.
auto rend() noexcept
Returns an iterator to the element following the last element of the reversed expression.
auto cend() const noexcept
Returns a constant iterator to the element following the last element of the expression.
auto cbegin() const noexcept
Returns a constant iterator to the first element of the expression.
reference back()
Returns a reference to the last element of the expression.
const inner_shape_type & shape() const noexcept
Returns the shape of the expression.
bool has_linear_assign(const S &strides) const
Checks whether the xfunctor_applier_base can be linearly assigned to an expression with the specified...
auto rbegin() noexcept
Returns an iterator to the first element of the reversed expression.
xfunctor_applier_base(Func &&, E &&) noexcept
Constructs an xfunctor_applier_base expression wrappering the specified xt::xexpression.
auto begin() noexcept
Returns an iterator to the first element of the expression.
reference front()
Returns a reference to the first element of the expression.
bool broadcast_shape(S &shape, bool reuse_cache=false) const
Broadcast the shape of the function to the specified parameter.
size_type size() const noexcept
Returns the size of the expression.
auto crend() const noexcept
Returns a constant iterator to the element following the last element of the reversed expression.
const inner_strides_type & strides() const noexcept
Returns the strides of the expression.
auto crbegin() const noexcept
Returns a constant iterator to the first element of the reversed expression.
View of an xexpression .
Implementation of the xsemantic_base interface for multidimensional views.
auto operator*(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< detail::multiplies, E1, E2 >
Multiplication.
auto equal(E1 &&e1, E2 &&e2) noexcept -> detail::xfunction_type_t< detail::equal_to, E1, E2 >
Element-wise equality.
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 broadcast(E &&e, const S &s)
Returns an xexpression broadcasting the given expression to a specified shape.
bool operator==(const xaxis_iterator< CT > &lhs, const xaxis_iterator< CT > &rhs)
Checks equality of the iterators.
layout_type
Definition xlayout.hpp:24