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 "../core/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
42 using iterable_types = xiterable_inner_types<D>;
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>
49 using layout_iterator = xiterator<stepper, inner_shape_type*, L>;
50 template <layout_type L>
51 using const_layout_iterator = xiterator<const_stepper, inner_shape_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
57 using linear_iterator = layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
58 using const_linear_iterator = const_layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
59 using reverse_linear_iterator = reverse_layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
60 using const_reverse_linear_iterator = const_reverse_layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
61
62 template <class S, layout_type L>
63 using broadcast_iterator = xiterator<stepper, S, L>;
64 template <class S, layout_type L>
65 using const_broadcast_iterator = xiterator<const_stepper, S, 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
71 using iterator = layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
72 using const_iterator = const_layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
73 using reverse_iterator = reverse_layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
74 using const_reverse_iterator = const_reverse_layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
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
157 using base_type = xconst_iterable<D>;
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>
195 layout_iterator<L> begin() noexcept;
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:
215
216 template <layout_type L>
217 layout_iterator<L> get_begin(bool end_index) noexcept;
218 template <layout_type L>
219 layout_iterator<L> get_end(bool end_index) noexcept;
220
221 template <layout_type L, class S>
222 broadcast_iterator<S, L> get_begin(const S& shape, bool end_index) noexcept;
223 template <layout_type L, class S>
224 broadcast_iterator<S, L> get_end(const S& shape, bool end_index) noexcept;
225
226 template <class S>
227 stepper get_stepper_begin(const S& shape) noexcept;
228 template <class S>
229 stepper get_stepper_end(const S& shape, layout_type l) noexcept;
230
231 template <class S>
232 const_stepper get_stepper_begin(const S& shape) const noexcept;
233 template <class S>
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
243 template <class D>
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;
277 using iterator_type = get_storage_iterator<storage_type, std::is_const<storage_type>::value>;
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
317 using inner_types = xcontainer_inner_types<D>;
318
319 using iterable_base = xiterable<D>;
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 template <layout_type L>
326 using layout_iterator = typename iterable_base::template layout_iterator<L>;
327 template <layout_type L>
328 using const_layout_iterator = typename iterable_base::template const_layout_iterator<L>;
329 template <layout_type L>
330 using reverse_layout_iterator = typename iterable_base::template reverse_layout_iterator<L>;
331 template <layout_type L>
332 using const_reverse_layout_iterator = typename iterable_base::template const_reverse_layout_iterator<L>;
333
334 template <class S, layout_type L>
335 using broadcast_iterator = typename iterable_base::template broadcast_iterator<S, L>;
336 template <class S, layout_type L>
337 using const_broadcast_iterator = typename iterable_base::template const_broadcast_iterator<S, L>;
338 template <class S, layout_type L>
339 using reverse_broadcast_iterator = typename iterable_base::template reverse_broadcast_iterator<S, L>;
340 template <class S, layout_type L>
341 using const_reverse_broadcast_iterator = typename iterable_base::template const_reverse_broadcast_iterator<S, L>;
342
343 using linear_traits = detail::linear_iterator_traits<D>;
344 using linear_iterator = typename linear_traits::linear_iterator;
345 using const_linear_iterator = typename linear_traits::const_linear_iterator;
346 using reverse_linear_iterator = typename linear_traits::reverse_linear_iterator;
347 using const_reverse_linear_iterator = typename linear_traits::const_reverse_linear_iterator;
348
349 template <layout_type L, class It1, class It2>
350 using select_iterator_impl = std::conditional_t<L == static_layout, It1, It2>;
351
352 template <layout_type L>
353 using select_iterator = select_iterator_impl<L, linear_iterator, layout_iterator<L>>;
354 template <layout_type L>
355 using select_const_iterator = select_iterator_impl<L, const_linear_iterator, const_layout_iterator<L>>;
356 template <layout_type L>
357 using select_reverse_iterator = select_iterator_impl<L, reverse_linear_iterator, reverse_layout_iterator<L>>;
358 template <layout_type L>
359 using select_const_reverse_iterator = select_iterator_impl<
360 L,
361 const_reverse_linear_iterator,
362 const_reverse_layout_iterator<L>>;
363
364 using iterator = select_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
365 using const_iterator = select_const_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
366 using reverse_iterator = select_reverse_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
367 using const_reverse_iterator = select_const_reverse_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
368
369 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
370 select_iterator<L> begin() noexcept;
371 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
372 select_iterator<L> end() noexcept;
373
374 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
375 select_const_iterator<L> begin() const noexcept;
376 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
377 select_const_iterator<L> end() const noexcept;
378 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
379 select_const_iterator<L> cbegin() const noexcept;
380 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
381 select_const_iterator<L> cend() const noexcept;
382
383 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
384 select_reverse_iterator<L> rbegin() noexcept;
385 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
386 select_reverse_iterator<L> rend() noexcept;
387
388 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
389 select_const_reverse_iterator<L> rbegin() const noexcept;
390 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
391 select_const_reverse_iterator<L> rend() const noexcept;
392 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
393 select_const_reverse_iterator<L> crbegin() const noexcept;
394 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
395 select_const_reverse_iterator<L> crend() const noexcept;
396
397 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
398 broadcast_iterator<S, L> begin(const S& shape) noexcept;
399 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
400 broadcast_iterator<S, L> end(const S& shape) noexcept;
401
402 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
403 const_broadcast_iterator<S, L> begin(const S& shape) const noexcept;
404 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
405 const_broadcast_iterator<S, L> end(const S& shape) const noexcept;
406 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
407 const_broadcast_iterator<S, L> cbegin(const S& shape) const noexcept;
408 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
409 const_broadcast_iterator<S, L> cend(const S& shape) const noexcept;
410
411 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
412 reverse_broadcast_iterator<S, L> rbegin(const S& shape) noexcept;
413 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
414 reverse_broadcast_iterator<S, L> rend(const S& shape) noexcept;
415
416 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
417 const_reverse_broadcast_iterator<S, L> rbegin(const S& shape) const noexcept;
418 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
419 const_reverse_broadcast_iterator<S, L> rend(const S& shape) const noexcept;
420 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
421 const_reverse_broadcast_iterator<S, L> crbegin(const S& shape) const noexcept;
422 template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
423 const_reverse_broadcast_iterator<S, L> crend(const S& shape) const noexcept;
424
425 private:
426
427 derived_type& derived_cast();
428 const derived_type& derived_cast() const;
429
430 friend class xiterable<D>;
431 friend class xconst_iterable<D>;
432 };
433
434 /**********************************
435 * xconst_iterable implementation *
436 **********************************/
437
442
446 template <class D>
447 template <layout_type L>
448 inline auto xconst_iterable<D>::begin() const noexcept -> const_layout_iterator<L>
449 {
450 return this->template cbegin<L>();
451 }
452
458 template <class D>
459 template <layout_type L>
460 inline auto xconst_iterable<D>::end() const noexcept -> const_layout_iterator<L>
461 {
462 return this->template cend<L>();
463 }
464
469 template <class D>
470 template <layout_type L>
471 inline auto xconst_iterable<D>::cbegin() const noexcept -> const_layout_iterator<L>
472 {
473 return this->template get_cbegin<L>(false);
474 }
475
481 template <class D>
482 template <layout_type L>
483 inline auto xconst_iterable<D>::cend() const noexcept -> const_layout_iterator<L>
484 {
485 return this->template get_cend<L>(true);
486 }
487
489
494
498 template <class D>
499 template <layout_type L>
500 inline auto xconst_iterable<D>::rbegin() const noexcept -> const_reverse_layout_iterator<L>
501 {
502 return this->template crbegin<L>();
503 }
504
510 template <class D>
511 template <layout_type L>
512 inline auto xconst_iterable<D>::rend() const noexcept -> const_reverse_layout_iterator<L>
513 {
514 return this->template crend<L>();
515 }
516
521 template <class D>
522 template <layout_type L>
523 inline auto xconst_iterable<D>::crbegin() const noexcept -> const_reverse_layout_iterator<L>
524 {
525 return const_reverse_layout_iterator<L>(get_cend<L>(true));
526 }
527
533 template <class D>
534 template <layout_type L>
535 inline auto xconst_iterable<D>::crend() const noexcept -> const_reverse_layout_iterator<L>
536 {
537 return const_reverse_layout_iterator<L>(get_cbegin<L>(false));
538 }
539
541
546
553 template <class D>
554 template <layout_type L, class S>
555 inline auto xconst_iterable<D>::begin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
556 {
557 return cbegin<L>(shape);
558 }
559
567 template <class D>
568 template <layout_type L, class S>
569 inline auto xconst_iterable<D>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
570 {
571 return cend<L>(shape);
572 }
573
581 template <class D>
582 template <layout_type L, class S>
583 inline auto xconst_iterable<D>::cbegin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
584 {
585 return get_cbegin<L, S>(shape, false);
586 }
587
595 template <class D>
596 template <layout_type L, class S>
597 inline auto xconst_iterable<D>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
598 {
599 return get_cend<L, S>(shape, true);
600 }
601
603
608
615 template <class D>
616 template <layout_type L, class S>
617 inline auto xconst_iterable<D>::rbegin(const S& shape) const noexcept
618 -> const_reverse_broadcast_iterator<S, L>
619 {
620 return crbegin<L, S>(shape);
621 }
622
630 template <class D>
631 template <layout_type L, class S>
632 inline auto xconst_iterable<D>::rend(const S& shape) const noexcept
633 -> const_reverse_broadcast_iterator<S, L>
634 {
635 return crend<L, S>(shape);
636 }
637
645 template <class D>
646 template <layout_type L, class S>
647 inline auto xconst_iterable<D>::crbegin(const S& shape) const noexcept
648 -> const_reverse_broadcast_iterator<S, L>
649 {
650 return const_reverse_broadcast_iterator<S, L>(get_cend<L, S>(shape, true));
651 }
652
660 template <class D>
661 template <layout_type L, class S>
662 inline auto xconst_iterable<D>::crend(const S& shape) const noexcept
663 -> const_reverse_broadcast_iterator<S, L>
664 {
665 return const_reverse_broadcast_iterator<S, L>(get_cbegin<L, S>(shape, false));
666 }
667
669
670 template <class D>
671 template <layout_type L>
672 inline auto xconst_iterable<D>::get_cbegin(bool end_index) const noexcept -> const_layout_iterator<L>
673 {
674 return const_layout_iterator<L>(get_stepper_begin(get_shape()), &get_shape(), end_index);
675 }
676
677 template <class D>
678 template <layout_type L>
679 inline auto xconst_iterable<D>::get_cend(bool end_index) const noexcept -> const_layout_iterator<L>
680 {
681 return const_layout_iterator<L>(get_stepper_end(get_shape(), L), &get_shape(), end_index);
682 }
683
684 template <class D>
685 template <layout_type L, class S>
686 inline auto xconst_iterable<D>::get_cbegin(const S& shape, bool end_index) const noexcept
687 -> const_broadcast_iterator<S, L>
688 {
689 return const_broadcast_iterator<S, L>(get_stepper_begin(shape), shape, end_index);
690 }
691
692 template <class D>
693 template <layout_type L, class S>
694 inline auto xconst_iterable<D>::get_cend(const S& shape, bool end_index) const noexcept
695 -> const_broadcast_iterator<S, L>
696 {
697 return const_broadcast_iterator<S, L>(get_stepper_end(shape, L), shape, end_index);
698 }
699
700 template <class D>
701 template <class S>
702 inline auto xconst_iterable<D>::get_stepper_begin(const S& shape) const noexcept -> const_stepper
703 {
704 return derived_cast().stepper_begin(shape);
705 }
706
707 template <class D>
708 template <class S>
709 inline auto xconst_iterable<D>::get_stepper_end(const S& shape, layout_type l) const noexcept
710 -> const_stepper
711 {
712 return derived_cast().stepper_end(shape, l);
713 }
714
715 template <class D>
716 inline auto xconst_iterable<D>::get_shape() const -> const inner_shape_type&
717 {
718 return derived_cast().shape();
719 }
720
721 template <class D>
722 inline auto xconst_iterable<D>::derived_cast() const -> const derived_type&
723 {
724 return *static_cast<const derived_type*>(this);
725 }
726
727 /****************************
728 * xiterable implementation *
729 ****************************/
730
735
739 template <class D>
740 template <layout_type L>
741 inline auto xiterable<D>::begin() noexcept -> layout_iterator<L>
742 {
743 return get_begin<L>(false);
744 }
745
751 template <class D>
752 template <layout_type L>
753 inline auto xiterable<D>::end() noexcept -> layout_iterator<L>
754 {
755 return get_end<L>(true);
756 }
757
759
764
768 template <class D>
769 template <layout_type L>
770 inline auto xiterable<D>::rbegin() noexcept -> reverse_layout_iterator<L>
771 {
772 return reverse_layout_iterator<L>(get_end<L>(true));
773 }
774
780 template <class D>
781 template <layout_type L>
782 inline auto xiterable<D>::rend() noexcept -> reverse_layout_iterator<L>
783 {
784 return reverse_layout_iterator<L>(get_begin<L>(false));
785 }
786
788
793
800 template <class D>
801 template <layout_type L, class S>
802 inline auto xiterable<D>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
803 {
804 return get_begin<L, S>(shape, false);
805 }
806
814 template <class D>
815 template <layout_type L, class S>
816 inline auto xiterable<D>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
817 {
818 return get_end<L, S>(shape, true);
819 }
820
822
827
834 template <class D>
835 template <layout_type L, class S>
836 inline auto xiterable<D>::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
837 {
838 return reverse_broadcast_iterator<S, L>(get_end<L, S>(shape, true));
839 }
840
848 template <class D>
849 template <layout_type L, class S>
850 inline auto xiterable<D>::rend(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
851 {
852 return reverse_broadcast_iterator<S, L>(get_begin<L, S>(shape, false));
853 }
854
856
857 template <class D>
858 template <layout_type L>
859 inline auto xiterable<D>::get_begin(bool end_index) noexcept -> layout_iterator<L>
860 {
861 return layout_iterator<L>(get_stepper_begin(this->get_shape()), &(this->get_shape()), end_index);
862 }
863
864 template <class D>
865 template <layout_type L>
866 inline auto xiterable<D>::get_end(bool end_index) noexcept -> layout_iterator<L>
867 {
868 return layout_iterator<L>(get_stepper_end(this->get_shape(), L), &(this->get_shape()), end_index);
869 }
870
871 template <class D>
872 template <layout_type L, class S>
873 inline auto xiterable<D>::get_begin(const S& shape, bool end_index) noexcept -> broadcast_iterator<S, L>
874 {
875 return broadcast_iterator<S, L>(get_stepper_begin(shape), shape, end_index);
876 }
877
878 template <class D>
879 template <layout_type L, class S>
880 inline auto xiterable<D>::get_end(const S& shape, bool end_index) noexcept -> broadcast_iterator<S, L>
881 {
882 return broadcast_iterator<S, L>(get_stepper_end(shape, L), shape, end_index);
883 }
884
885 template <class D>
886 template <class S>
887 inline auto xiterable<D>::get_stepper_begin(const S& shape) noexcept -> stepper
888 {
889 return derived_cast().stepper_begin(shape);
890 }
891
892 template <class D>
893 template <class S>
894 inline auto xiterable<D>::get_stepper_end(const S& shape, layout_type l) noexcept -> stepper
895 {
896 return derived_cast().stepper_end(shape, l);
897 }
898
899 template <class D>
900 template <class S>
901 inline auto xiterable<D>::get_stepper_begin(const S& shape) const noexcept -> const_stepper
902 {
903 return derived_cast().stepper_begin(shape);
904 }
905
906 template <class D>
907 template <class S>
908 inline auto xiterable<D>::get_stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper
909 {
910 return derived_cast().stepper_end(shape, l);
911 }
912
913 template <class D>
914 inline auto xiterable<D>::derived_cast() -> derived_type&
915 {
916 return *static_cast<derived_type*>(this);
917 }
918
919 /***************************************
920 * xcontiguous_iterable implementation *
921 ***************************************/
922
927
931 template <class D>
932 template <layout_type L>
933 inline auto xcontiguous_iterable<D>::begin() noexcept -> select_iterator<L>
934 {
935 if constexpr (L == static_layout)
936 {
937 return derived_cast().linear_begin();
938 }
939 else
940 {
941 return iterable_base::template begin<L>();
942 }
943 }
944
950 template <class D>
951 template <layout_type L>
952 inline auto xcontiguous_iterable<D>::end() noexcept -> select_iterator<L>
953 {
954 if constexpr (L == static_layout)
955 {
956 return derived_cast().linear_end();
957 }
958 else
959 {
960 return iterable_base::template end<L>();
961 }
962 }
963
968 template <class D>
969 template <layout_type L>
970 inline auto xcontiguous_iterable<D>::begin() const noexcept -> select_const_iterator<L>
971 {
972 return this->template cbegin<L>();
973 }
974
980 template <class D>
981 template <layout_type L>
982 inline auto xcontiguous_iterable<D>::end() const noexcept -> select_const_iterator<L>
983 {
984 return this->template cend<L>();
985 }
986
991 template <class D>
992 template <layout_type L>
993 inline auto xcontiguous_iterable<D>::cbegin() const noexcept -> select_const_iterator<L>
994 {
995 if constexpr (L == static_layout)
996 {
997 return derived_cast().linear_cbegin();
998 }
999 else
1000 {
1001 return iterable_base::template cbegin<L>();
1002 }
1003 }
1004
1010 template <class D>
1011 template <layout_type L>
1012 inline auto xcontiguous_iterable<D>::cend() const noexcept -> select_const_iterator<L>
1013 {
1014 if constexpr (L == static_layout)
1015 {
1016 return derived_cast().linear_cend();
1017 }
1018 else
1019 {
1020 return iterable_base::template cend<L>();
1021 }
1022 }
1023
1025
1030
1034 template <class D>
1035 template <layout_type L>
1036 inline auto xcontiguous_iterable<D>::rbegin() noexcept -> select_reverse_iterator<L>
1037 {
1038 if constexpr (L == static_layout)
1039 {
1040 return derived_cast().linear_rbegin();
1041 }
1042 else
1043 {
1044 return iterable_base::template rbegin<L>();
1045 }
1046 }
1047
1053 template <class D>
1054 template <layout_type L>
1055 inline auto xcontiguous_iterable<D>::rend() noexcept -> select_reverse_iterator<L>
1056 {
1057 if constexpr (L == static_layout)
1058 {
1059 return derived_cast().linear_rend();
1060 }
1061 else
1062 {
1063 return iterable_base::template rend<L>();
1064 }
1065 }
1066
1071 template <class D>
1072 template <layout_type L>
1073 inline auto xcontiguous_iterable<D>::rbegin() const noexcept -> select_const_reverse_iterator<L>
1074 {
1075 return this->template crbegin<L>();
1076 }
1077
1083 template <class D>
1084 template <layout_type L>
1085 inline auto xcontiguous_iterable<D>::rend() const noexcept -> select_const_reverse_iterator<L>
1086 {
1087 return this->template crend<L>();
1088 }
1089
1094 template <class D>
1095 template <layout_type L>
1096 inline auto xcontiguous_iterable<D>::crbegin() const noexcept -> select_const_reverse_iterator<L>
1097 {
1098 if constexpr (L == static_layout)
1099 {
1100 return derived_cast().linear_crbegin();
1101 }
1102 else
1103 {
1104 return iterable_base::template crbegin<L>();
1105 }
1106 }
1107
1113 template <class D>
1114 template <layout_type L>
1115 inline auto xcontiguous_iterable<D>::crend() const noexcept -> select_const_reverse_iterator<L>
1116 {
1117 if constexpr (L == static_layout)
1118 {
1119 return derived_cast().linear_crend();
1120 }
1121 else
1122 {
1123 return iterable_base::template crend<L>();
1124 }
1125 }
1126
1128
1132
1141 template <class D>
1142 template <layout_type L, class S>
1143 inline auto xcontiguous_iterable<D>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
1144 {
1145 return iterable_base::template begin<L, S>(shape);
1146 }
1147
1155 template <class D>
1156 template <layout_type L, class S>
1157 inline auto xcontiguous_iterable<D>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
1158 {
1159 return iterable_base::template end<L, S>(shape);
1160 }
1161
1169 template <class D>
1170 template <layout_type L, class S>
1171 inline auto xcontiguous_iterable<D>::begin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
1172 {
1173 return iterable_base::template begin<L, S>(shape);
1174 }
1175
1183 template <class D>
1184 template <layout_type L, class S>
1185 inline auto xcontiguous_iterable<D>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
1186 {
1187 return iterable_base::template end<L, S>(shape);
1188 }
1189
1197 template <class D>
1198 template <layout_type L, class S>
1199 inline auto xcontiguous_iterable<D>::cbegin(const S& shape) const noexcept
1200 -> const_broadcast_iterator<S, L>
1201 {
1202 return iterable_base::template cbegin<L, S>(shape);
1203 }
1204
1212 template <class D>
1213 template <layout_type L, class S>
1214 inline auto xcontiguous_iterable<D>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
1215 {
1216 return iterable_base::template cend<L, S>(shape);
1217 }
1218
1220
1225
1232 template <class D>
1233 template <layout_type L, class S>
1234 inline auto xcontiguous_iterable<D>::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
1235 {
1236 return iterable_base::template rbegin<L, S>(shape);
1237 }
1238
1246 template <class D>
1247 template <layout_type L, class S>
1248 inline auto xcontiguous_iterable<D>::rend(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
1249 {
1250 return iterable_base::template rend<L, S>(shape);
1251 }
1252
1260 template <class D>
1261 template <layout_type L, class S>
1262 inline auto xcontiguous_iterable<D>::rbegin(const S& shape) const noexcept
1263 -> const_reverse_broadcast_iterator<S, L>
1264 {
1265 return iterable_base::template rbegin<L, S>(shape);
1266 }
1267
1275 template <class D>
1276 template <layout_type L, class S>
1277 inline auto xcontiguous_iterable<D>::rend(const S& shape) const noexcept
1278 -> const_reverse_broadcast_iterator<S, L>
1279 {
1280 return iterable_base::template rend<L, S>(shape);
1281 }
1282
1290 template <class D>
1291 template <layout_type L, class S>
1292 inline auto xcontiguous_iterable<D>::crbegin(const S& shape) const noexcept
1293 -> const_reverse_broadcast_iterator<S, L>
1294 {
1295 return iterable_base::template crbegin<L, S>(shape);
1296 }
1297
1305 template <class D>
1306 template <layout_type L, class S>
1307 inline auto xcontiguous_iterable<D>::crend(const S& shape) const noexcept
1308 -> const_reverse_broadcast_iterator<S, L>
1309 {
1310 return iterable_base::template crend<L, S>(shape);
1311 }
1312
1314
1315 template <class D>
1316 inline auto xcontiguous_iterable<D>::derived_cast() -> derived_type&
1317 {
1318 return *static_cast<derived_type*>(this);
1319 }
1320
1321 template <class D>
1322 inline auto xcontiguous_iterable<D>::derived_cast() const -> const derived_type&
1323 {
1324 return *static_cast<const derived_type*>(this);
1325 }
1326
1327}
1328
1329#endif
Base class for multidimensional iterable constant expressions.
Definition xiterable.hpp:37
Base class for multidimensional iterable expressions with contiguous storage.
auto cend() const noexcept -> select_const_iterator< L >
auto cbegin() const noexcept -> select_const_iterator< L >
auto rbegin() noexcept -> select_reverse_iterator< L >
auto crbegin() const noexcept -> select_const_reverse_iterator< L >
auto begin() noexcept -> select_iterator< L >
auto rend() noexcept -> select_reverse_iterator< L >
auto crend() const noexcept -> select_const_reverse_iterator< L >
Base class for multidimensional iterable expressions.
standard mathematical functions for xexpressions
layout_type
Definition xlayout.hpp:24