xtensor
Loading...
Searching...
No Matches
xiterable.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_ITERABLE_HPP
11#define XTENSOR_ITERABLE_HPP
12
13#include "xiterator.hpp"
14
15namespace xt
16{
17
18 /*******************
19 * xconst_iterable *
20 *******************/
21
22 template <class D>
24
35 template <class D>
37 {
38 public:
39
40 using derived_type = D;
41
43 using inner_shape_type = typename iterable_types::inner_shape_type;
44
45 using stepper = typename iterable_types::stepper;
46 using const_stepper = typename iterable_types::const_stepper;
47
48 template <layout_type L>
50 template <layout_type L>
52 template <layout_type L>
53 using reverse_layout_iterator = std::reverse_iterator<layout_iterator<L>>;
54 template <layout_type L>
55 using const_reverse_layout_iterator = std::reverse_iterator<const_layout_iterator<L>>;
56
61
62 template <class S, layout_type L>
64 template <class S, layout_type L>
66 template <class S, layout_type L>
67 using reverse_broadcast_iterator = std::reverse_iterator<broadcast_iterator<S, L>>;
68 template <class S, layout_type L>
69 using const_reverse_broadcast_iterator = std::reverse_iterator<const_broadcast_iterator<S, L>>;
70
75
76 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
77 const_layout_iterator<L> begin() const noexcept;
78 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
79 const_layout_iterator<L> end() const noexcept;
80 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
81 const_layout_iterator<L> cbegin() const noexcept;
82 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
83 const_layout_iterator<L> cend() const noexcept;
84
85 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
86 const_reverse_layout_iterator<L> rbegin() const noexcept;
87 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
88 const_reverse_layout_iterator<L> rend() const noexcept;
89 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
90 const_reverse_layout_iterator<L> crbegin() const noexcept;
91 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
92 const_reverse_layout_iterator<L> crend() const noexcept;
93
94 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
95 const_broadcast_iterator<S, L> begin(const S& shape) const noexcept;
96 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
97 const_broadcast_iterator<S, L> end(const S& shape) const noexcept;
98 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
99 const_broadcast_iterator<S, L> cbegin(const S& shape) const noexcept;
100 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
101 const_broadcast_iterator<S, L> cend(const S& shape) const noexcept;
102
103 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
104 const_reverse_broadcast_iterator<S, L> rbegin(const S& shape) const noexcept;
105 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
106 const_reverse_broadcast_iterator<S, L> rend(const S& shape) const noexcept;
107 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
108 const_reverse_broadcast_iterator<S, L> crbegin(const S& shape) const noexcept;
109 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
110 const_reverse_broadcast_iterator<S, L> crend(const S& shape) const noexcept;
111
112 protected:
113
114 const inner_shape_type& get_shape() const;
115
116 private:
117
118 template <layout_type L>
119 const_layout_iterator<L> get_cbegin(bool end_index) const noexcept;
120 template <layout_type L>
121 const_layout_iterator<L> get_cend(bool end_index) const noexcept;
122
123 template <layout_type L, class S>
124 const_broadcast_iterator<S, L> get_cbegin(const S& shape, bool end_index) const noexcept;
125 template <layout_type L, class S>
126 const_broadcast_iterator<S, L> get_cend(const S& shape, bool end_index) const noexcept;
127
128 template <class S>
129 const_stepper get_stepper_begin(const S& shape) const noexcept;
130 template <class S>
131 const_stepper get_stepper_end(const S& shape, layout_type l) const noexcept;
132
133 const derived_type& derived_cast() const;
134 };
135
136 /*************
137 * xiterable *
138 *************/
139
150 template <class D>
151 class xiterable : public xconst_iterable<D>
152 {
153 public:
154
155 using derived_type = D;
156
158 using inner_shape_type = typename base_type::inner_shape_type;
159
160 using stepper = typename base_type::stepper;
161 using const_stepper = typename base_type::const_stepper;
162
163 using linear_iterator = typename base_type::linear_iterator;
164 using reverse_linear_iterator = typename base_type::reverse_linear_iterator;
165
166 template <layout_type L>
167 using layout_iterator = typename base_type::template layout_iterator<L>;
168 template <layout_type L>
169 using const_layout_iterator = typename base_type::template const_layout_iterator<L>;
170 template <layout_type L>
171 using reverse_layout_iterator = typename base_type::template reverse_layout_iterator<L>;
172 template <layout_type L>
173 using const_reverse_layout_iterator = typename base_type::template const_reverse_layout_iterator<L>;
174
175 template <class S, layout_type L>
176 using broadcast_iterator = typename base_type::template broadcast_iterator<S, L>;
177 template <class S, layout_type L>
178 using const_broadcast_iterator = typename base_type::template const_broadcast_iterator<S, L>;
179 template <class S, layout_type L>
180 using reverse_broadcast_iterator = typename base_type::template reverse_broadcast_iterator<S, L>;
181 template <class S, layout_type L>
182 using const_reverse_broadcast_iterator = typename base_type::template const_reverse_broadcast_iterator<S, L>;
183
184 using iterator = typename base_type::iterator;
185 using const_iterator = typename base_type::const_iterator;
186 using reverse_iterator = typename base_type::reverse_iterator;
187 using const_reverse_iterator = typename base_type::const_reverse_iterator;
188
189 using base_type::begin;
190 using base_type::end;
191 using base_type::rbegin;
192 using base_type::rend;
193
194 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
196 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
197 layout_iterator<L> end() noexcept;
198
199 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
200 reverse_layout_iterator<L> rbegin() noexcept;
201 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
202 reverse_layout_iterator<L> rend() noexcept;
203
204 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
205 broadcast_iterator<S, L> begin(const S& shape) noexcept;
206 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
207 broadcast_iterator<S, L> end(const S& shape) noexcept;
208
209 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
210 reverse_broadcast_iterator<S, L> rbegin(const S& shape) noexcept;
211 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
212 reverse_broadcast_iterator<S, L> rend(const S& shape) noexcept;
213
214 private:
217 layout_iterator<L> get_begin(bool end_index) noexcept;
219 layout_iterator<L> get_end(bool end_index) noexcept;
220
222 broadcast_iterator<S, L> get_begin(const S& shape, bool end_index) noexcept;
224 broadcast_iterator<S, L> get_end(const S& shape, bool end_index) noexcept;
225
227 stepper get_stepper_begin(const S& shape) noexcept;
229 stepper get_stepper_end(const S& shape, layout_type l) noexcept;
230
232 const_stepper get_stepper_begin(const S& shape) const noexcept;
234 const_stepper get_stepper_end(const S& shape, layout_type l) const noexcept;
235
236 derived_type& derived_cast();
237 };
238
239 /************************
240 * xcontiguous_iterable *
241 ************************/
242
245
246 namespace detail
247 {
248 template <class T, bool is_const>
249 struct get_storage_iterator;
250
251 template <class T>
252 struct get_storage_iterator<T, true>
253 {
254 using iterator = typename T::const_iterator;
255 using const_iterator = typename T::const_iterator;
256 using reverse_iterator = typename T::const_reverse_iterator;
257 using const_reverse_iterator = typename T::const_reverse_iterator;
258 };
259
260 template <class T>
261 struct get_storage_iterator<T, false>
262 {
263 using iterator = typename T::iterator;
264 using const_iterator = typename T::const_iterator;
265 using reverse_iterator = typename T::reverse_iterator;
266 using const_reverse_iterator = typename T::const_reverse_iterator;
267 };
268
269 template <class D, bool has_storage_type>
270 struct linear_iterator_traits_impl;
271
272 template <class D>
273 struct linear_iterator_traits_impl<D, true>
274 {
275 using inner_types = xcontainer_inner_types<D>;
276 using storage_type = typename inner_types::storage_type;
278 using linear_iterator = typename iterator_type::iterator;
279 using const_linear_iterator = typename iterator_type::const_iterator;
280 using reverse_linear_iterator = typename iterator_type::reverse_iterator;
281 using const_reverse_linear_iterator = typename iterator_type::const_reverse_iterator;
282 };
283
284 template <class D>
285 struct linear_iterator_traits_impl<D, false>
286 {
287 using inner_types = xcontainer_inner_types<D>;
288 using xexpression_type = typename inner_types::xexpression_type;
289 using linear_iterator = typename xexpression_type::linear_iterator;
290 using const_linear_iterator = typename xexpression_type::const_linear_iterator;
291 using reverse_linear_iterator = typename xexpression_type::reverse_linear_iterator;
292 using const_reverse_linear_iterator = typename xexpression_type::const_reverse_linear_iterator;
293 };
294
295 template <class D>
296 using linear_iterator_traits = linear_iterator_traits_impl<D, has_storage_type<D>::value>;
297 }
298
310 template <class D>
312 {
313 public:
314
315 using derived_type = D;
316
318
320 using stepper = typename iterable_base::stepper;
321 using const_stepper = typename iterable_base::const_stepper;
322
323 static constexpr layout_type static_layout = inner_types::layout;
324
325#if defined(_MSC_VER) && _MSC_VER >= 1910
326 // Workaround for compiler bug in Visual Studio 2017 with respect to alias templates with non-type
327 // parameters.
328 template <layout_type L>
330 template <layout_type L>
331 using const_layout_iterator = xiterator<
332 typename iterable_base::const_stepper,
333 typename iterable_base::inner_shape_type*,
334 L>;
335 template <layout_type L>
336 using reverse_layout_iterator = std::reverse_iterator<layout_iterator<L>>;
337 template <layout_type L>
338 using const_reverse_layout_iterator = std::reverse_iterator<const_layout_iterator<L>>;
339#else
340 template <layout_type L>
341 using layout_iterator = typename iterable_base::template layout_iterator<L>;
342 template <layout_type L>
343 using const_layout_iterator = typename iterable_base::template const_layout_iterator<L>;
344 template <layout_type L>
345 using reverse_layout_iterator = typename iterable_base::template reverse_layout_iterator<L>;
346 template <layout_type L>
347 using const_reverse_layout_iterator = typename iterable_base::template const_reverse_layout_iterator<L>;
348#endif
349
350 template <class S, layout_type L>
351 using broadcast_iterator = typename iterable_base::template broadcast_iterator<S, L>;
352 template <class S, layout_type L>
353 using const_broadcast_iterator = typename iterable_base::template const_broadcast_iterator<S, L>;
354 template <class S, layout_type L>
355 using reverse_broadcast_iterator = typename iterable_base::template reverse_broadcast_iterator<S, L>;
356 template <class S, layout_type L>
357 using const_reverse_broadcast_iterator = typename iterable_base::template const_reverse_broadcast_iterator<S, L>;
358
360 using linear_iterator = typename linear_traits::linear_iterator;
361 using const_linear_iterator = typename linear_traits::const_linear_iterator;
362 using reverse_linear_iterator = typename linear_traits::reverse_linear_iterator;
363 using const_reverse_linear_iterator = typename linear_traits::const_reverse_linear_iterator;
364
365 template <layout_type L, class It1, class It2>
366 using select_iterator_impl = std::conditional_t<L == static_layout, It1, It2>;
367
368 template <layout_type L>
370 template <layout_type L>
372 template <layout_type L>
374 template <layout_type L>
375 using select_const_reverse_iterator = select_iterator_impl<
376 L,
377 const_reverse_linear_iterator,
379
384
385 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
386 select_iterator<L> begin() noexcept;
387 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
388 select_iterator<L> end() noexcept;
389
390 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
391 select_const_iterator<L> begin() const noexcept;
392 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
393 select_const_iterator<L> end() const noexcept;
394 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
395 select_const_iterator<L> cbegin() const noexcept;
396 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
397 select_const_iterator<L> cend() const noexcept;
398
399 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
400 select_reverse_iterator<L> rbegin() noexcept;
401 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
402 select_reverse_iterator<L> rend() noexcept;
403
404 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
405 select_const_reverse_iterator<L> rbegin() const noexcept;
406 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
407 select_const_reverse_iterator<L> rend() const noexcept;
408 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
409 select_const_reverse_iterator<L> crbegin() const noexcept;
410 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
411 select_const_reverse_iterator<L> crend() const noexcept;
412
413 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
414 broadcast_iterator<S, L> begin(const S& shape) noexcept;
415 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
416 broadcast_iterator<S, L> end(const S& shape) noexcept;
417
418 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
419 const_broadcast_iterator<S, L> begin(const S& shape) const noexcept;
420 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
421 const_broadcast_iterator<S, L> end(const S& shape) const noexcept;
422 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
423 const_broadcast_iterator<S, L> cbegin(const S& shape) const noexcept;
424 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
425 const_broadcast_iterator<S, L> cend(const S& shape) const noexcept;
426
427 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
428 reverse_broadcast_iterator<S, L> rbegin(const S& shape) noexcept;
429 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
430 reverse_broadcast_iterator<S, L> rend(const S& shape) noexcept;
431
432 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
433 const_reverse_broadcast_iterator<S, L> rbegin(const S& shape) const noexcept;
434 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
435 const_reverse_broadcast_iterator<S, L> rend(const S& shape) const noexcept;
436 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
437 const_reverse_broadcast_iterator<S, L> crbegin(const S& shape) const noexcept;
438 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
439 const_reverse_broadcast_iterator<S, L> crend(const S& shape) const noexcept;
440
441 private:
442
443 derived_type& derived_cast();
444 const derived_type& derived_cast() const;
445
446 friend class xiterable<D>;
447 friend class xconst_iterable<D>;
448 };
449
450 /**********************************
451 * xconst_iterable implementation *
452 **********************************/
453
462 template <class D>
463 template <layout_type L>
465 {
466 return this->template cbegin<L>();
467 }
468
474 template <class D>
475 template <layout_type L>
477 {
478 return this->template cend<L>();
479 }
480
485 template <class D>
486 template <layout_type L>
488 {
489 return this->template get_cbegin<L>(false);
490 }
491
497 template <class D>
498 template <layout_type L>
500 {
501 return this->template get_cend<L>(true);
502 }
503
505
514 template <class D>
515 template <layout_type L>
516 inline auto xconst_iterable<D>::rbegin() const noexcept -> const_reverse_layout_iterator<L>
517 {
518 return this->template crbegin<L>();
519 }
520
526 template <class D>
527 template <layout_type L>
528 inline auto xconst_iterable<D>::rend() const noexcept -> const_reverse_layout_iterator<L>
529 {
530 return this->template crend<L>();
531 }
532
537 template <class D>
538 template <layout_type L>
539 inline auto xconst_iterable<D>::crbegin() const noexcept -> const_reverse_layout_iterator<L>
540 {
542 }
543
549 template <class D>
550 template <layout_type L>
551 inline auto xconst_iterable<D>::crend() const noexcept -> const_reverse_layout_iterator<L>
552 {
554 }
555
557
569 template <class D>
570 template <layout_type L, class S>
571 inline auto xconst_iterable<D>::begin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
572 {
573 return cbegin<L>(shape);
574 }
575
583 template <class D>
584 template <layout_type L, class S>
585 inline auto xconst_iterable<D>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
586 {
587 return cend<L>(shape);
588 }
589
597 template <class D>
598 template <layout_type L, class S>
599 inline auto xconst_iterable<D>::cbegin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
600 {
601 return get_cbegin<L, S>(shape, false);
602 }
603
611 template <class D>
612 template <layout_type L, class S>
613 inline auto xconst_iterable<D>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
614 {
615 return get_cend<L, S>(shape, true);
616 }
617
619
631 template <class D>
632 template <layout_type L, class S>
633 inline auto xconst_iterable<D>::rbegin(const S& shape) const noexcept
635 {
636 return crbegin<L, S>(shape);
637 }
638
646 template <class D>
647 template <layout_type L, class S>
648 inline auto xconst_iterable<D>::rend(const S& shape) const noexcept
650 {
651 return crend<L, S>(shape);
652 }
653
661 template <class D>
662 template <layout_type L, class S>
663 inline auto xconst_iterable<D>::crbegin(const S& shape) const noexcept
665 {
667 }
668
676 template <class D>
677 template <layout_type L, class S>
678 inline auto xconst_iterable<D>::crend(const S& shape) const noexcept
680 {
682 }
683
685
686 template <class D>
687 template <layout_type L>
688 inline auto xconst_iterable<D>::get_cbegin(bool end_index) const noexcept -> const_layout_iterator<L>
689 {
690 return const_layout_iterator<L>(get_stepper_begin(get_shape()), &get_shape(), end_index);
691 }
692
693 template <class D>
694 template <layout_type L>
695 inline auto xconst_iterable<D>::get_cend(bool end_index) const noexcept -> const_layout_iterator<L>
696 {
697 return const_layout_iterator<L>(get_stepper_end(get_shape(), L), &get_shape(), end_index);
698 }
699
700 template <class D>
701 template <layout_type L, class S>
702 inline auto xconst_iterable<D>::get_cbegin(const S& shape, bool end_index) const noexcept
703 -> const_broadcast_iterator<S, L>
704 {
705 return const_broadcast_iterator<S, L>(get_stepper_begin(shape), shape, end_index);
706 }
707
708 template <class D>
709 template <layout_type L, class S>
710 inline auto xconst_iterable<D>::get_cend(const S& shape, bool end_index) const noexcept
711 -> const_broadcast_iterator<S, L>
712 {
713 return const_broadcast_iterator<S, L>(get_stepper_end(shape, L), shape, end_index);
714 }
715
716 template <class D>
717 template <class S>
718 inline auto xconst_iterable<D>::get_stepper_begin(const S& shape) const noexcept -> const_stepper
719 {
720 return derived_cast().stepper_begin(shape);
721 }
722
723 template <class D>
724 template <class S>
725 inline auto xconst_iterable<D>::get_stepper_end(const S& shape, layout_type l) const noexcept
726 -> const_stepper
727 {
728 return derived_cast().stepper_end(shape, l);
729 }
730
731 template <class D>
732 inline auto xconst_iterable<D>::get_shape() const -> const inner_shape_type&
733 {
734 return derived_cast().shape();
735 }
736
737 template <class D>
738 inline auto xconst_iterable<D>::derived_cast() const -> const derived_type&
739 {
740 return *static_cast<const derived_type*>(this);
741 }
742
743 /****************************
744 * xiterable implementation *
745 ****************************/
746
755 template <class D>
756 template <layout_type L>
757 inline auto xiterable<D>::begin() noexcept -> layout_iterator<L>
758 {
759 return get_begin<L>(false);
760 }
761
767 template <class D>
768 template <layout_type L>
769 inline auto xiterable<D>::end() noexcept -> layout_iterator<L>
770 {
771 return get_end<L>(true);
772 }
773
775
784 template <class D>
785 template <layout_type L>
786 inline auto xiterable<D>::rbegin() noexcept -> reverse_layout_iterator<L>
787 {
789 }
790
796 template <class D>
797 template <layout_type L>
798 inline auto xiterable<D>::rend() noexcept -> reverse_layout_iterator<L>
799 {
801 }
802
804
816 template <class D>
817 template <layout_type L, class S>
818 inline auto xiterable<D>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
819 {
820 return get_begin<L, S>(shape, false);
821 }
822
830 template <class D>
831 template <layout_type L, class S>
832 inline auto xiterable<D>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
833 {
834 return get_end<L, S>(shape, true);
835 }
836
838
850 template <class D>
851 template <layout_type L, class S>
852 inline auto xiterable<D>::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
853 {
855 }
856
864 template <class D>
865 template <layout_type L, class S>
866 inline auto xiterable<D>::rend(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
867 {
869 }
870
872
873 template <class D>
874 template <layout_type L>
875 inline auto xiterable<D>::get_begin(bool end_index) noexcept -> layout_iterator<L>
876 {
877 return layout_iterator<L>(get_stepper_begin(this->get_shape()), &(this->get_shape()), end_index);
878 }
879
880 template <class D>
881 template <layout_type L>
882 inline auto xiterable<D>::get_end(bool end_index) noexcept -> layout_iterator<L>
883 {
884 return layout_iterator<L>(get_stepper_end(this->get_shape(), L), &(this->get_shape()), end_index);
885 }
886
887 template <class D>
888 template <layout_type L, class S>
889 inline auto xiterable<D>::get_begin(const S& shape, bool end_index) noexcept -> broadcast_iterator<S, L>
890 {
891 return broadcast_iterator<S, L>(get_stepper_begin(shape), shape, end_index);
892 }
893
894 template <class D>
895 template <layout_type L, class S>
896 inline auto xiterable<D>::get_end(const S& shape, bool end_index) noexcept -> broadcast_iterator<S, L>
897 {
898 return broadcast_iterator<S, L>(get_stepper_end(shape, L), shape, end_index);
899 }
900
901 template <class D>
902 template <class S>
903 inline auto xiterable<D>::get_stepper_begin(const S& shape) noexcept -> stepper
904 {
905 return derived_cast().stepper_begin(shape);
906 }
907
908 template <class D>
909 template <class S>
910 inline auto xiterable<D>::get_stepper_end(const S& shape, layout_type l) noexcept -> stepper
911 {
912 return derived_cast().stepper_end(shape, l);
913 }
914
915 template <class D>
916 template <class S>
917 inline auto xiterable<D>::get_stepper_begin(const S& shape) const noexcept -> const_stepper
918 {
919 return derived_cast().stepper_begin(shape);
920 }
921
922 template <class D>
923 template <class S>
924 inline auto xiterable<D>::get_stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper
925 {
926 return derived_cast().stepper_end(shape, l);
927 }
928
929 template <class D>
930 inline auto xiterable<D>::derived_cast() -> derived_type&
931 {
932 return *static_cast<derived_type*>(this);
933 }
934
935 /***************************************
936 * xcontiguous_iterable implementation *
937 ***************************************/
938
947 template <class D>
948 template <layout_type L>
950 {
951 return xtl::mpl::static_if<L == static_layout>(
952 [&](auto self)
953 {
954 return self(*this).derived_cast().linear_begin();
955 },
956 /*else*/
957 [&](auto self)
958 {
959 return self(*this).iterable_base::template begin<L>();
960 }
961 );
962 }
963
969 template <class D>
970 template <layout_type L>
972 {
973 return xtl::mpl::static_if<L == static_layout>(
974 [&](auto self)
975 {
976 return self(*this).derived_cast().linear_end();
977 },
978 /*else*/
979 [&](auto self)
980 {
981 return self(*this).iterable_base::template end<L>();
982 }
983 );
984 }
985
990 template <class D>
991 template <layout_type L>
993 {
994 return this->template cbegin<L>();
995 }
996
1002 template <class D>
1003 template <layout_type L>
1005 {
1006 return this->template cend<L>();
1007 }
1008
1013 template <class D>
1014 template <layout_type L>
1016 {
1017 return xtl::mpl::static_if<L == static_layout>(
1018 [&](auto self)
1019 {
1020 return self(*this).derived_cast().linear_cbegin();
1021 },
1022 /*else*/
1023 [&](auto self)
1024 {
1025 return self(*this).iterable_base::template cbegin<L>();
1026 }
1027 );
1028 }
1029
1035 template <class D>
1036 template <layout_type L>
1038 {
1039 return xtl::mpl::static_if<L == static_layout>(
1040 [&](auto self)
1041 {
1042 return self(*this).derived_cast().linear_cend();
1043 },
1044 /*else*/
1045 [&](auto self)
1046 {
1047 return self(*this).iterable_base::template cend<L>();
1048 }
1049 );
1050 }
1051
1053
1062 template <class D>
1063 template <layout_type L>
1065 {
1066 return xtl::mpl::static_if<L == static_layout>(
1067 [&](auto self)
1068 {
1069 return self(*this).derived_cast().linear_rbegin();
1070 },
1071 /*else*/
1072 [&](auto self)
1073 {
1074 return self(*this).iterable_base::template rbegin<L>();
1075 }
1076 );
1077 }
1078
1084 template <class D>
1085 template <layout_type L>
1087 {
1088 return xtl::mpl::static_if<L == static_layout>(
1089 [&](auto self)
1090 {
1091 return self(*this).derived_cast().linear_rend();
1092 },
1093 /*else*/
1094 [&](auto self)
1095 {
1096 return self(*this).iterable_base::template rend<L>();
1097 }
1098 );
1099 }
1100
1105 template <class D>
1106 template <layout_type L>
1108 {
1109 return this->template crbegin<L>();
1110 }
1111
1117 template <class D>
1118 template <layout_type L>
1120 {
1121 return this->template crend<L>();
1122 }
1123
1128 template <class D>
1129 template <layout_type L>
1131 {
1132 return xtl::mpl::static_if<L == static_layout>(
1133 [&](auto self)
1134 {
1135 return self(*this).derived_cast().linear_crbegin();
1136 },
1137 /*else*/
1138 [&](auto self)
1139 {
1140 return self(*this).iterable_base::template crbegin<L>();
1141 }
1142 );
1143 }
1144
1150 template <class D>
1151 template <layout_type L>
1153 {
1154 return xtl::mpl::static_if<L == static_layout>(
1155 [&](auto self)
1156 {
1157 return self(*this).derived_cast().linear_crend();
1158 },
1159 /*else*/
1160 [&](auto self)
1161 {
1162 return self(*this).iterable_base::template crend<L>();
1163 }
1164 );
1165 }
1166
1168
1181 template <class D>
1182 template <layout_type L, class S>
1183 inline auto xcontiguous_iterable<D>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
1184 {
1185 return iterable_base::template begin<L, S>(shape);
1186 }
1187
1195 template <class D>
1196 template <layout_type L, class S>
1197 inline auto xcontiguous_iterable<D>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
1198 {
1199 return iterable_base::template end<L, S>(shape);
1200 }
1201
1209 template <class D>
1210 template <layout_type L, class S>
1211 inline auto xcontiguous_iterable<D>::begin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
1212 {
1213 return iterable_base::template begin<L, S>(shape);
1214 }
1215
1223 template <class D>
1224 template <layout_type L, class S>
1225 inline auto xcontiguous_iterable<D>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
1226 {
1227 return iterable_base::template end<L, S>(shape);
1228 }
1229
1237 template <class D>
1238 template <layout_type L, class S>
1239 inline auto xcontiguous_iterable<D>::cbegin(const S& shape) const noexcept
1241 {
1242 return iterable_base::template cbegin<L, S>(shape);
1243 }
1244
1252 template <class D>
1253 template <layout_type L, class S>
1254 inline auto xcontiguous_iterable<D>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
1255 {
1256 return iterable_base::template cend<L, S>(shape);
1257 }
1258
1260
1272 template <class D>
1273 template <layout_type L, class S>
1275 {
1276 return iterable_base::template rbegin<L, S>(shape);
1277 }
1278
1286 template <class D>
1287 template <layout_type L, class S>
1289 {
1290 return iterable_base::template rend<L, S>(shape);
1291 }
1292
1300 template <class D>
1301 template <layout_type L, class S>
1302 inline auto xcontiguous_iterable<D>::rbegin(const S& shape) const noexcept
1304 {
1305 return iterable_base::template rbegin<L, S>(shape);
1306 }
1307
1315 template <class D>
1316 template <layout_type L, class S>
1317 inline auto xcontiguous_iterable<D>::rend(const S& shape) const noexcept
1319 {
1320 return iterable_base::template rend<L, S>(shape);
1321 }
1322
1330 template <class D>
1331 template <layout_type L, class S>
1332 inline auto xcontiguous_iterable<D>::crbegin(const S& shape) const noexcept
1334 {
1335 return iterable_base::template crbegin<L, S>(shape);
1336 }
1337
1345 template <class D>
1346 template <layout_type L, class S>
1347 inline auto xcontiguous_iterable<D>::crend(const S& shape) const noexcept
1349 {
1350 return iterable_base::template crend<L, S>(shape);
1351 }
1352
1354
1355 template <class D>
1356 inline auto xcontiguous_iterable<D>::derived_cast() -> derived_type&
1357 {
1358 return *static_cast<derived_type*>(this);
1359 }
1360
1361 template <class D>
1362 inline auto xcontiguous_iterable<D>::derived_cast() const -> const derived_type&
1363 {
1364 return *static_cast<const derived_type*>(this);
1365 }
1366
1367}
1368
1369#endif
Base class for multidimensional iterable constant expressions.
Definition xiterable.hpp:37
Base class for multidimensional iterable expressions with contiguous storage.
Base class for multidimensional iterable expressions.
standard mathematical functions for xexpressions
layout_type
Definition xlayout.hpp:24