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#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
359 using linear_traits = detail::linear_iterator_traits<D>;
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>
369 using select_iterator = select_iterator_impl<L, linear_iterator, layout_iterator<L>>;
370 template <layout_type L>
371 using select_const_iterator = select_iterator_impl<L, const_linear_iterator, const_layout_iterator<L>>;
372 template <layout_type L>
373 using select_reverse_iterator = select_iterator_impl<L, reverse_linear_iterator, reverse_layout_iterator<L>>;
374 template <layout_type L>
375 using select_const_reverse_iterator = select_iterator_impl<
376 L,
377 const_reverse_linear_iterator,
378 const_reverse_layout_iterator<L>>;
379
380 using iterator = select_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
381 using const_iterator = select_const_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
382 using reverse_iterator = select_reverse_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
383 using const_reverse_iterator = select_const_reverse_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
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
458
462 template <class D>
463 template <layout_type L>
464 inline auto xconst_iterable<D>::begin() const noexcept -> const_layout_iterator<L>
465 {
466 return this->template cbegin<L>();
467 }
468
474 template <class D>
475 template <layout_type L>
476 inline auto xconst_iterable<D>::end() const noexcept -> const_layout_iterator<L>
477 {
478 return this->template cend<L>();
479 }
480
485 template <class D>
486 template <layout_type L>
487 inline auto xconst_iterable<D>::cbegin() const noexcept -> const_layout_iterator<L>
488 {
489 return this->template get_cbegin<L>(false);
490 }
491
497 template <class D>
498 template <layout_type L>
499 inline auto xconst_iterable<D>::cend() const noexcept -> const_layout_iterator<L>
500 {
501 return this->template get_cend<L>(true);
502 }
503
505
510
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 {
541 return const_reverse_layout_iterator<L>(get_cend<L>(true));
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 {
553 return const_reverse_layout_iterator<L>(get_cbegin<L>(false));
554 }
555
557
562
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
624
631 template <class D>
632 template <layout_type L, class S>
633 inline auto xconst_iterable<D>::rbegin(const S& shape) const noexcept
634 -> const_reverse_broadcast_iterator<S, L>
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
649 -> const_reverse_broadcast_iterator<S, L>
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
664 -> const_reverse_broadcast_iterator<S, L>
665 {
666 return const_reverse_broadcast_iterator<S, L>(get_cend<L, S>(shape, true));
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
679 -> const_reverse_broadcast_iterator<S, L>
680 {
681 return const_reverse_broadcast_iterator<S, L>(get_cbegin<L, S>(shape, false));
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
751
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
780
784 template <class D>
785 template <layout_type L>
786 inline auto xiterable<D>::rbegin() noexcept -> reverse_layout_iterator<L>
787 {
788 return reverse_layout_iterator<L>(get_end<L>(true));
789 }
790
796 template <class D>
797 template <layout_type L>
798 inline auto xiterable<D>::rend() noexcept -> reverse_layout_iterator<L>
799 {
800 return reverse_layout_iterator<L>(get_begin<L>(false));
801 }
802
804
809
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
843
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 {
854 return reverse_broadcast_iterator<S, L>(get_end<L, S>(shape, true));
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 {
868 return reverse_broadcast_iterator<S, L>(get_begin<L, S>(shape, false));
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
943
947 template <class D>
948 template <layout_type L>
949 inline auto xcontiguous_iterable<D>::begin() noexcept -> select_iterator<L>
950 {
951 if constexpr (L == static_layout)
952 {
953 return derived_cast().linear_begin();
954 }
955 else
956 {
957 return iterable_base::template begin<L>();
958 }
959 }
960
966 template <class D>
967 template <layout_type L>
968 inline auto xcontiguous_iterable<D>::end() noexcept -> select_iterator<L>
969 {
970 if constexpr (L == static_layout)
971 {
972 return derived_cast().linear_end();
973 }
974 else
975 {
976 return iterable_base::template end<L>();
977 }
978 }
979
984 template <class D>
985 template <layout_type L>
986 inline auto xcontiguous_iterable<D>::begin() const noexcept -> select_const_iterator<L>
987 {
988 return this->template cbegin<L>();
989 }
990
996 template <class D>
997 template <layout_type L>
998 inline auto xcontiguous_iterable<D>::end() const noexcept -> select_const_iterator<L>
999 {
1000 return this->template cend<L>();
1001 }
1002
1007 template <class D>
1008 template <layout_type L>
1009 inline auto xcontiguous_iterable<D>::cbegin() const noexcept -> select_const_iterator<L>
1010 {
1011 if constexpr (L == static_layout)
1012 {
1013 return derived_cast().linear_cbegin();
1014 }
1015 else
1016 {
1017 return iterable_base::template cbegin<L>();
1018 }
1019 }
1020
1026 template <class D>
1027 template <layout_type L>
1028 inline auto xcontiguous_iterable<D>::cend() const noexcept -> select_const_iterator<L>
1029 {
1030 if constexpr (L == static_layout)
1031 {
1032 return derived_cast().linear_cend();
1033 }
1034 else
1035 {
1036 return iterable_base::template cend<L>();
1037 }
1038 }
1039
1041
1046
1050 template <class D>
1051 template <layout_type L>
1052 inline auto xcontiguous_iterable<D>::rbegin() noexcept -> select_reverse_iterator<L>
1053 {
1054 if constexpr (L == static_layout)
1055 {
1056 return derived_cast().linear_rbegin();
1057 }
1058 else
1059 {
1060 return iterable_base::template rbegin<L>();
1061 }
1062 }
1063
1069 template <class D>
1070 template <layout_type L>
1071 inline auto xcontiguous_iterable<D>::rend() noexcept -> select_reverse_iterator<L>
1072 {
1073 if constexpr (L == static_layout)
1074 {
1075 return derived_cast().linear_rend();
1076 }
1077 else
1078 {
1079 return iterable_base::template rend<L>();
1080 }
1081 }
1082
1087 template <class D>
1088 template <layout_type L>
1089 inline auto xcontiguous_iterable<D>::rbegin() const noexcept -> select_const_reverse_iterator<L>
1090 {
1091 return this->template crbegin<L>();
1092 }
1093
1099 template <class D>
1100 template <layout_type L>
1101 inline auto xcontiguous_iterable<D>::rend() const noexcept -> select_const_reverse_iterator<L>
1102 {
1103 return this->template crend<L>();
1104 }
1105
1110 template <class D>
1111 template <layout_type L>
1112 inline auto xcontiguous_iterable<D>::crbegin() const noexcept -> select_const_reverse_iterator<L>
1113 {
1114 if constexpr (L == static_layout)
1115 {
1116 return derived_cast().linear_crbegin();
1117 }
1118 else
1119 {
1120 return iterable_base::template crbegin<L>();
1121 }
1122 }
1123
1129 template <class D>
1130 template <layout_type L>
1131 inline auto xcontiguous_iterable<D>::crend() const noexcept -> select_const_reverse_iterator<L>
1132 {
1133 if constexpr (L == static_layout)
1134 {
1135 return derived_cast().linear_crend();
1136 }
1137 else
1138 {
1139 return iterable_base::template crend<L>();
1140 }
1141 }
1142
1144
1148
1157 template <class D>
1158 template <layout_type L, class S>
1159 inline auto xcontiguous_iterable<D>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
1160 {
1161 return iterable_base::template begin<L, S>(shape);
1162 }
1163
1171 template <class D>
1172 template <layout_type L, class S>
1173 inline auto xcontiguous_iterable<D>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
1174 {
1175 return iterable_base::template end<L, S>(shape);
1176 }
1177
1185 template <class D>
1186 template <layout_type L, class S>
1187 inline auto xcontiguous_iterable<D>::begin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
1188 {
1189 return iterable_base::template begin<L, S>(shape);
1190 }
1191
1199 template <class D>
1200 template <layout_type L, class S>
1201 inline auto xcontiguous_iterable<D>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
1202 {
1203 return iterable_base::template end<L, S>(shape);
1204 }
1205
1213 template <class D>
1214 template <layout_type L, class S>
1215 inline auto xcontiguous_iterable<D>::cbegin(const S& shape) const noexcept
1216 -> const_broadcast_iterator<S, L>
1217 {
1218 return iterable_base::template cbegin<L, S>(shape);
1219 }
1220
1228 template <class D>
1229 template <layout_type L, class S>
1230 inline auto xcontiguous_iterable<D>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
1231 {
1232 return iterable_base::template cend<L, S>(shape);
1233 }
1234
1236
1241
1248 template <class D>
1249 template <layout_type L, class S>
1250 inline auto xcontiguous_iterable<D>::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
1251 {
1252 return iterable_base::template rbegin<L, S>(shape);
1253 }
1254
1262 template <class D>
1263 template <layout_type L, class S>
1264 inline auto xcontiguous_iterable<D>::rend(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
1265 {
1266 return iterable_base::template rend<L, S>(shape);
1267 }
1268
1276 template <class D>
1277 template <layout_type L, class S>
1278 inline auto xcontiguous_iterable<D>::rbegin(const S& shape) const noexcept
1279 -> const_reverse_broadcast_iterator<S, L>
1280 {
1281 return iterable_base::template rbegin<L, S>(shape);
1282 }
1283
1291 template <class D>
1292 template <layout_type L, class S>
1293 inline auto xcontiguous_iterable<D>::rend(const S& shape) const noexcept
1294 -> const_reverse_broadcast_iterator<S, L>
1295 {
1296 return iterable_base::template rend<L, S>(shape);
1297 }
1298
1306 template <class D>
1307 template <layout_type L, class S>
1308 inline auto xcontiguous_iterable<D>::crbegin(const S& shape) const noexcept
1309 -> const_reverse_broadcast_iterator<S, L>
1310 {
1311 return iterable_base::template crbegin<L, S>(shape);
1312 }
1313
1321 template <class D>
1322 template <layout_type L, class S>
1323 inline auto xcontiguous_iterable<D>::crend(const S& shape) const noexcept
1324 -> const_reverse_broadcast_iterator<S, L>
1325 {
1326 return iterable_base::template crend<L, S>(shape);
1327 }
1328
1330
1331 template <class D>
1332 inline auto xcontiguous_iterable<D>::derived_cast() -> derived_type&
1333 {
1334 return *static_cast<derived_type*>(this);
1335 }
1336
1337 template <class D>
1338 inline auto xcontiguous_iterable<D>::derived_cast() const -> const derived_type&
1339 {
1340 return *static_cast<const derived_type*>(this);
1341 }
1342
1343}
1344
1345#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