asgn
 
Loading...
Searching...
No Matches
tagged.hpp
1#ifndef tagged_hpp_
2#define tagged_hpp_
3
4#include <concepts>
5#include <tuple>
6#include <ostream>
7#include <vector>
8#include <variant>
9
10namespace tagged {
11
14
15 // TAG
16
17 namespace impl {
18 template< typename T>
19 struct tag_traits;
20 }
21
27 template< typename T>
28 concept tag = impl::tag_traits<T>::is_tag;
29
35 template< typename T>
36 concept selector_tag = impl::tag_traits<T>::is_selector;
37
42 template< tag T>
43 using selector = typename impl::tag_traits<T>::selector;
44
46 template< typename T1, typename T2>
47 concept same_selector = std::same_as< selector<T1>, selector<T2>>;
48
49 struct tag_base {};
50
51 template< tag T, std::size_t b, std::size_t e, typename RP>
52 struct srr_tag;
53
54 template< tag T, std::size_t b, std::size_t e>
55 struct sr_tag {
56 static constexpr bool is_tag = true;
57 static constexpr bool is_direct = false;
58 using core = sr_tag< T, b, e>;
59 static constexpr bool is_selector = false;
60 using selector = T;
61 template<selector_tag T2>
62 using retag = sr_tag< T2, b, e>;
63 template<typename RP>
64 using set_roundup = srr_tag<T, b, e, RP>;
65
66 static constexpr bool is_static = true;
67 static constexpr std::size_t begin = b;
68 static constexpr std::size_t end = e;
69 };
70
71 template< tag T, std::size_t b, std::size_t e, typename RP>
72 struct srr_tag : sr_tag< T, b, e> {
73 static constexpr bool has_roundup = true;
74 using roundup_policy = RP;
75
76 using core = srr_tag< T, b, e, RP>;
77 template<selector_tag T2>
78 using retag = srr_tag< T2, b, e, RP>;
79 template<typename RP2>
80 using set_roundup = srr_tag< T, b, e, RP2>;
81 };
82
83 template< tag T, typename RP>
84 struct r_tag {
85 static constexpr bool is_tag = true;
86 static constexpr bool is_direct = false;
87 using core = r_tag< T, RP>;
88 static constexpr bool is_selector = false;
89 using selector = T;
90 template<selector_tag T2>
91 using retag = r_tag< T2, RP>;
92
93 static constexpr bool has_roundup = true;
94 using roundup_policy = RP;
95 template<typename RP2>
96 using set_roundup = r_tag< T, RP2>;
97 };
98
99 namespace impl {
100 template< typename T>
101 requires T::is_tag
102 struct tag_traits<T>
103 {
104 static constexpr bool is_tag = true;
105 static constexpr bool is_direct = false;
106 using core = typename T::core;
107 static constexpr bool is_selector = T::is_selector;
108 using selector = typename T::selector;
109 template<selector_tag T2>
110 using retag = typename T::template retag<T2>;
111 template<typename RP>
112 using set_roundup = typename T::template set_roundup<RP>;
113 };
114
115 template< typename T>
116 requires std::derived_from<T, tag_base>
117 struct tag_traits<T>
118 {
119 static constexpr bool is_tag = true;
120 static constexpr bool is_direct = true;
121 using core = T;
122 static constexpr bool is_selector = true;
123 using selector = T;
124 template<selector_tag T2>
125 using retag = T2;
126 template<typename RP>
127 using set_roundup = r_tag<T, RP>;
128 };
129 };
130
131 template< tag T>
132 using core = typename impl::tag_traits<T>::core;
133
134 template< typename T1, typename T2>
135 concept same_tag = std::same_as< core<T1>, core<T2>>;
136
137 template< selector_tag T2, tag T>
138 using retag = typename impl::tag_traits<T>::template retag<T2>;
139
140 template< tag T, typename RP>
141 using set_roundup = typename impl::tag_traits<T>::template set_roundup<RP>;
142
143 template< typename T>
144 concept static_tag = tag<T> && T::is_static;
145
146 template< typename T>
147 concept non_static_tag = tag<T> && (!static_tag<T>);
148
149 template< static_tag T1, static_tag T2>
150 inline constexpr bool same_static_range = T1::begin == T2::begin && T1::end == T2::end;
151
152 // CARRIER
153
154 template< tag T>
155 using index_carrier_type = std::size_t;
157
159 template< tag ... TL>
160 class index_class;
161
162 template< tag ... TL>
163 class iterator_class;
164
165 template< tag T, std::size_t D>
167
168 template< tag ... TL>
169 class range_class;
170
171 template< typename E, tag ... TL>
172 class tensor_view;
174
176 namespace impl {
177 struct range_base {};
178 }
179
180 template< typename T>
181 concept is_range = std::derived_from< T, impl::range_base>;
182
183 namespace impl {
184 struct index_base {};
185
186 template< tag T, tag ... TL>
187 struct element_traits;
188
189 template< tag T>
190 struct element_traits< T> : std::false_type {};
191
192 template< tag T, tag T2, tag ... TL>
193 requires same_selector<T, T2>
194 struct element_traits< T, T2, TL ...> : std::true_type {};
195
196 template< tag T, tag T2, tag ... TL>
197 requires (!same_selector<T, T2>)
198 struct element_traits< T, T2, TL ...> : element_traits< T, TL ...> {};
199
200 template< typename T, typename ... TL>
201 concept one_of = element_traits< T, TL...>::value;
202
203 template< tag T, tag ... TL>
204 struct position_traits;
205
206 template< tag T, tag T2, tag ... TL>
207 requires same_selector<T, T2>
208 struct position_traits< T, T2, TL ...>
209 : std::integral_constant< std::size_t, 0>
210 {};
211
212 template< tag T, tag T2, tag ... TL>
213 requires (!same_selector<T, T2>)
214 struct position_traits< T, T2, TL ...>
215 : std::integral_constant< std::size_t, position_traits< T, TL ...>::value + 1>
216 {};
217
218 template< typename T, typename ... TL>
219 inline constexpr std::size_t position_of = position_traits< T, TL...>::value;
220 }
222
227 template< typename ... TL>
228 struct tag_list {};
229
231 namespace impl {
232 template< typename TA, typename TB>
233 struct concat_traits;
234
235 template< tag TA, tag TB>
236 struct concat_traits< TA, TB> {
237 using type = tag_list< TA, TB>;
238 };
239
240 template< tag TA, tag ... LB>
241 struct concat_traits< TA, tag_list< LB ...>> {
242 using type = tag_list< TA, LB ...>;
243 };
244
245 template< typename TA, typename TB>
246 using concat_list = typename concat_traits< TA, TB>::type;
247
248 template< typename LA, typename LB>
249 struct subtract_traits;
250
251 template< tag ... TLA>
252 struct subtract_traits< tag_list<TLA...>, tag_list<>> {
253 using type = tag_list<TLA...>;
254 };
255
256 template< tag TA, tag ... TLA, tag TB>
257 requires same_selector< TA, TB>
258 struct subtract_traits< tag_list<TA, TLA...>, tag_list<TB>>
259 {
260 using type = tag_list<TLA ...>;
261 };
262
263 template< tag TA, tag ... TLA, tag TB>
264 requires (!same_selector< TA, TB>)
265 struct subtract_traits< tag_list<TA, TLA...>, tag_list<TB>>
266 {
267 private:
268 using removed_a = typename subtract_traits< tag_list<TLA ...>, tag_list<TB>>::type;
269 public:
270 using type = concat_list< TA, removed_a>;
271 };
272
273 template< tag ... TLA, tag TB, tag ... TLB>
274 struct subtract_traits< tag_list<TLA...>, tag_list<TB, TLB...>>
275 {
276 private:
277 using removed_a = typename subtract_traits<tag_list<TLA...>, tag_list<TB>>::type;
278 public:
279 using type = typename subtract_traits<removed_a, tag_list<TLB ...>>::type;
280 };
281
282 template< selector_tag T, tag ... TL>
283 struct pick_traits;
284
285 template< selector_tag T, tag T0, tag ... TL>
286 requires same_selector<T, T0>
287 struct pick_traits< T, T0, TL ...>
288 {
289 using type = T0;
290 };
291
292 template< selector_tag T, tag T0, tag ... TL>
293 requires (!same_selector<T, T0>)
294 struct pick_traits< T, T0, TL ...>
295 : pick_traits< T, TL ...>
296 {};
297
298 template< std::size_t I, tag ... TL>
299 struct pick_index_traits;
300
301 template< tag T0, tag ... TL>
302 struct pick_index_traits< 0, T0, TL ...>
303 {
304 using type = T0;
305 };
306
307 template< std::size_t I, tag T0, tag ... TL>
308 struct pick_index_traits< I, T0, TL ...>
309 : pick_index_traits< I-1, TL ...>
310 {};
311
312 template< typename A, typename B>
313 struct same_list_traits;
314
315 template< tag ... AL, tag ... BL>
316 requires (sizeof...(AL) == sizeof...(BL))
317 struct same_list_traits< tag_list<AL...>, tag_list<BL...>>
318 {
319 static constexpr bool value = (same_selector<AL, BL> && ...);
320 };
321
322 template< typename A, typename B>
323 concept same_selector_list = same_list_traits< A, B>::value;
324
325 template< typename A, typename B>
326 struct subset_traits;
327
328 template< tag ... AL, tag ... BL>
329 struct subset_traits< tag_list<AL...>, tag_list<BL...>>
330 {
331 static constexpr bool value = (one_of<AL, BL...> && ...);
332 };
333
334 template< typename A, typename B>
335 concept subset_selector = subset_traits< A, B>::value;
336 }
337
338 template< typename T, typename ... TL>
339 requires impl::one_of<T, TL...>
340 using pick = typename impl::pick_traits< T, TL...>::type;
341
342 template< std::size_t I, typename ... TL>
343 requires (I < sizeof...(TL))
344 using pick_index = typename impl::pick_index_traits< I, TL...>::type;
346
353 template< tag T>
354 class index_class< T> : public impl::index_base {
355 public:
356 index_class() noexcept
357 : i_(0)
358 {}
359 constexpr explicit index_class(index_carrier_type< T> v) noexcept
360 : i_(v)
361 {}
362 template< tag T2>
363 index_class< T2> retag() const
364 {
365 return index_class< T2>(i_);
366 }
367 index_carrier_type<T> value() const noexcept
368 {
369 return i_;
370 }
371 template< std::size_t I>
372 requires (I == 0)
373 auto&& get() const noexcept
374 {
375 return std::get< I>(i_);
376 }
377 template< same_selector<T> T2>
378 auto&& get() const noexcept
379 {
380 return *this;
381 }
382 private:
383 index_carrier_type< T> i_;
384 };
385
387 template< tag T>
388 std::ostream& operator<<(std::ostream& o, index_class<T> v)
389 {
390 o << v.value();
391 return o;
392 }
393
394 template< tag T>
395 bool operator==(index_class<T> a, index_class<T> b)
396 {
397 return a.value() == b.value();
398 }
399
400 template< tag T>
401 bool operator!=(index_class<T> a, index_class<T> b)
402 {
403 return a.value() != b.value();
404 }
406
407 template< tag T, index_carrier_type<T> D>
409
410 template< tag T, index_carrier_type<T> E>
411 class static_sentinel_class {
412 public:
413 using difference_type = std::make_signed_t<index_carrier_type<T>>;
414
415 static_sentinel_class() noexcept
416 {
417 }
418
419 bool operator==(const iterator_class<T>& b) const noexcept
420 {
421 return E == b.v_;
422 }
423 bool operator!=(const iterator_class<T>& b) const noexcept
424 {
425 return E != b.v_;
426 }
427
428 template<index_carrier_type<T> D>
429 bool operator==(const strided_iterator_class<T, D>& b) const noexcept
430 {
431 return E == b.v_;
432 }
433 template<index_carrier_type<T> D>
434 bool operator!=(const strided_iterator_class<T, D>& b) const noexcept
435 {
436 return E != b.v_;
437 }
438 };
439
441 template< tag T>
442 class iterator_class< T> {
443 public:
444 iterator_class() noexcept
445 : v_(0)
446 {}
447 explicit iterator_class(index_carrier_type< T> v) noexcept
448 : v_(v)
449 {}
450 template<index_carrier_type<T> E>
451 iterator_class(const static_sentinel_class<T, E>& b) noexcept
452 : v_(E)
453 {
454 }
455 index_class< T> operator*() const noexcept
456 {
457 return index_class< T>(v_);
458 }
459 bool operator==(const iterator_class<T>& b) const noexcept
460 {
461 return v_ == b.v_;
462 }
463 bool operator!=(const iterator_class<T>& b) const noexcept
464 {
465 return v_ != b.v_;
466 }
467 template<index_carrier_type<T> E>
468 bool operator==(const static_sentinel_class<T, E>& b) const noexcept
469 {
470 return v_ == E;
471 }
472 template<index_carrier_type<T> E>
473 bool operator!=(const static_sentinel_class<T, E>& b) const noexcept
474 {
475 return v_ != E;
476 }
477 iterator_class<T>& operator++() noexcept
478 {
479 ++v_;
480 return *this;
481 }
482 iterator_class<T> operator++(int) noexcept
483 {
484 auto tmp = *this;
485 operator++();
486 return tmp;
487 }
488 private:
489 index_carrier_type< T> v_;
490
491 template< tag T2, index_carrier_type<T2> E>
492 friend class static_sentinel_class;
493 };
494
495 template< tag T, index_carrier_type<T> D>
497 public:
498 using difference_type = std::make_signed_t<index_carrier_type<T>>;
499
500 strided_iterator_class() noexcept
501 : v_(0)
502 {
503 }
504 explicit strided_iterator_class(index_carrier_type< T> v) noexcept
505 : v_(v)
506 {
507 }
508 template<index_carrier_type<T> E>
509 strided_iterator_class(const static_sentinel_class<T, E>& b) noexcept
510 : v_(E)
511 {
512 }
513 index_class< T> operator*() const noexcept
514 {
515 return index_class< T>(v_);
516 }
517 bool operator==(const strided_iterator_class<T, D>& b) const noexcept
518 {
519 return v_ == b.v_;
520 }
521 bool operator!=(const strided_iterator_class<T, D>& b) const noexcept
522 {
523 return v_ != b.v_;
524 }
525 template<index_carrier_type<T> E>
526 bool operator==(const static_sentinel_class<T, E>& b) const noexcept
527 {
528 return v_ == E;
529 }
530 template<index_carrier_type<T> E>
531 bool operator!=(const static_sentinel_class<T, E>& b) const noexcept
532 {
533 return v_ != E;
534 }
535 strided_iterator_class<T, D>& operator++() noexcept
536 {
537 v_ += D;
538 return *this;
539 }
540 strided_iterator_class<T, D> operator++(int) noexcept
541 {
542 auto tmp = *this;
543 operator++();
544 return tmp;
545 }
546 private:
547 index_carrier_type< T> v_;
548
549 template< tag T2, index_carrier_type<T> E>
550 friend class static_sentinel_class;
551 };
553
564 template< non_static_tag T>
565 class range_class< T> : public impl::range_base {
566 public:
567 using selector = tagged::selector<T>;
568
569 range_class() noexcept
570 : b_(0), e_(0)
571 {}
572 explicit range_class(index_carrier_type< T> e) noexcept
573 : b_(0), e_(e)
574 {}
575 range_class(index_carrier_type< T> b, index_carrier_type< T> e) noexcept
576 : b_(b), e_(e)
577 {}
578 range_class(const range_class<T>& b) = default;
579 range_class<T>& operator=(const range_class<T>& b) = default;
580 range_class(range_class<T>&& b) noexcept
581 : b_(b.b_), e_(b.e_)
582 {
583 b.b_ = 0;
584 b.e_ = 0;
585 }
586 range_class<T>& operator=(range_class<T>&& b) noexcept
587 {
588 b_ = b.b_;
589 e_ = b.e_;
590 b.b_ = 0;
591 b.e_ = 0;
592 return *this;
593 }
594 template< tag ... TL2>
595 requires (sizeof...(TL2) >= 1)
596 explicit range_class(const range_class< TL2...>& r) noexcept
597 : b_(r.template get<selector>().begin_value()), e_(r.template get<selector>().end_value())
598 {}
599 template<typename T2>
600 requires same_tag<T, T2>
601 bool operator==(const range_class<T2>& b) const
602 {
603 return b_ == b.begin_value() && e_ == b.end_value();
604 }
605 template<typename T2>
606 requires same_tag<T, T2>
607 bool operator!=(const range_class<T2>& b) const
608 {
609 return b_ != b.begin_value() || e_ != b.end_value();
610 }
611 template< tag T2>
612 range_class< T2> retag() const
613 {
614 return range_class< T2>(b_, e_);
615 }
616 template<typename T2>
617 requires same_selector<T, T2>
618 index_carrier_type<T> flat(const index_class< T2>& i) const
619 {
620 return i.value() - b_;
621 }
622 index_carrier_type<T> size() const
623 {
624 return e_ - b_;
625 }
626 template<std::size_t S>
627 requires (S > 0)
628 auto perfectly_strided() const
629 {
630 if ((e_ - b_) % S != 0)
631 {
632 throw std::logic_error("range is not perfectly strided");
633 }
634 using strided_iterator = strided_iterator_class<selector, S>;
635 return std::ranges::subrange<strided_iterator>(
636 strided_iterator(b_),
637 strided_iterator(e_));
638 }
639 iterator_class<selector> begin() const noexcept
640 {
641 return iterator_class<selector>(b_);
642 }
643 iterator_class<selector> end() const noexcept
644 {
645 return iterator_class<selector>(e_);
646 }
647 index_carrier_type<T> begin_value() const noexcept
648 {
649 return b_;
650 }
651 index_carrier_type<T> end_value() const noexcept
652 {
653 return e_;
654 }
655 template< same_selector< T> T2>
656 auto&& get() const noexcept
657 {
658 return *this;
659 }
660 template< std::size_t I>
661 requires (I == 0)
662 auto&& get() const noexcept
663 {
664 return *this;
665 }
666 template< std::size_t I>
667 requires (I == 0)
668 using get_tag = T;
669 private:
670 index_carrier_type< T> b_, e_;
671 };
672
674 template< static_tag T>
675 class range_class< T> : public impl::range_base {
676 public:
678
679 constexpr range_class() noexcept
680 {}
681 constexpr explicit range_class(index_carrier_type< T> e)
682 {
683 if (0 != T::begin || e != T::end)
684 {
685 throw std::logic_error("WTF");
686 }
687 }
688 constexpr range_class(index_carrier_type< T> b, index_carrier_type< T> e)
689 {
690 if (b != T::begin || e != T::end)
691 {
692 throw std::logic_error("WTF");
693 }
694 }
695 template< tag ... TL2>
696 requires (sizeof...(TL2) >= 1)
697 explicit range_class(const range_class< TL2...>&) noexcept
698 requires pick<selector, TL2...>::is_static
699 {}
700 template<typename T2>
701 requires same_selector<T, T2>
702 constexpr bool operator==(const range_class<T2>&) const
703 {
704 return same_static_range<T, T2>;
705 }
706 template<typename T2>
707 requires same_selector<T, T2>
708 constexpr bool operator!=(const range_class<T2>&) const
709 {
710 return !same_static_range<T, T2>;
711 }
712 template< static_tag T2>
713 static constexpr range_class< T2> retag()
714 {
715 return range_class< T2>();
716 }
717 static index_carrier_type<T> flat(const index_class< selector>& i)
718 {
719 return i.value() - T::begin;
720 }
721 static constexpr index_carrier_type<T> size()
722 {
723 return T::end - T::begin;
724 }
725 template<std::size_t S>
726 requires (S > 0)
727 auto perfectly_strided() const
728 {
729 static_assert((T::end - T::begin) % S == 0);
730 using strided_iterator = strided_iterator_class<selector, S>;
731 using static_sentinel = static_sentinel_class<selector, T::end>;
732 return std::ranges::subrange<strided_iterator, static_sentinel>(
733 strided_iterator(T::begin),
734 static_sentinel());
735 }
736 static iterator_class<selector> begin() noexcept
737 {
738 return iterator_class<selector>(T::begin);
739 }
740 static static_sentinel_class<selector, T::end> end() noexcept
741 {
742 return static_sentinel_class<selector, T::end>();
743 }
744 static constexpr index_carrier_type<T> begin_value() noexcept
745 {
746 return T::begin;
747 }
748 static constexpr index_carrier_type<T> end_value() noexcept
749 {
750 return T::end;
751 }
752 template< same_selector< T> T2>
753 static constexpr auto get() noexcept
754 {
755 return range_class<T>{};
756 }
757 template< std::size_t I>
758 requires (I == 0)
759 auto&& get() const noexcept
760 {
761 return *this;
762 }
763 template< std::size_t I>
764 requires (I == 0)
765 using get_tag = T;
766 };
768
769 template<std::size_t S, tag T>
770 requires (S > 0)
771 auto perfectly_strided(const range_class< T>& r)
772 {
773 return r.template perfectly_strided<S>();
774 }
775
783 template< tag ... TL>
784 class index_class : public impl::index_base {
785 public:
786 index_class() noexcept
787 : i_(index_carrier_type< TL>(0) ...)
788 {}
789 constexpr index_class(index_carrier_type< TL> ... vl) noexcept
790 : i_(index_class< TL>(vl) ...)
791 {}
792 index_class(index_class< TL> ... vl) noexcept
793 : i_(vl ...)
794 {}
800 template< std::size_t I>
801 requires (I < sizeof...(TL))
802 auto&& get() const noexcept
803 {
804 return std::get< I>(i_);
805 }
806
811 template< impl::one_of< TL ...> T>
812 auto&& get() const noexcept
813 {
814 return std::get< index_class< pick<selector<T>, TL...>>>(i_);
815 }
816 private:
817 std::tuple< index_class< TL> ...> i_;
818 };
819
821 template<>
822 class index_class<> : public impl::index_base {
823 public:
824 constexpr index_class() noexcept
825 {}
826 };
828
837 template< tag ... TL1, tag ... TL2>
838 index_class< TL1 ..., TL2 ...> operator&(const index_class< TL1 ...>& ia, const index_class< TL2 ...>& ib)
839 {
840 return index_class< TL1 ..., TL2 ...>(ia.template get< TL1>() ..., ib.template get< TL2>() ...);
841 }
842
844 template< tag T1, tag ... TL2>
845 std::ostream& operator<<(std::ostream& o, index_class<T1, TL2 ...> v)
846 {
847 ((o << "[" << v.template get<T1>()), ..., (o << "," << v.template get<TL2>())), o << "]";
848 return o;
849 }
851
853 template< tag ... TL>
854 class iterator_class {
855 public:
856 iterator_class() noexcept
857 : rngp_(nullptr), it_(iterator_class< TL>(0) ...)
858 {}
859 iterator_class(const range_class< TL...>* rngp, iterator_class< selector<TL>> ... v) noexcept
860 : rngp_(rngp), it_(v ...)
861 {}
862 index_class< selector<TL> ...> operator*() const noexcept
863 {
864 return index_class< selector<TL> ...>(*std::get< iterator_class< selector< TL>>>(it_)...);
865 }
866 bool operator==(const iterator_class<TL ...>& b) const noexcept
867 {
868 return equal< sizeof...(TL)>(b);
869 }
870 bool operator!=(const iterator_class<TL ...>& b) const noexcept
871 {
872 return !equal< sizeof...(TL)>(b);
873 }
874 iterator_class<TL ...>& operator++() noexcept
875 {
876 increment< sizeof...(TL)>();
877 return *this;
878 }
879 iterator_class<TL ...> operator++(int) noexcept
880 {
881 auto tmp = *this;
882 operator++();
883 return tmp;
884 }
885 private:
886 template< std::size_t I>
887 bool equal(const iterator_class<TL ...>& b) const noexcept
888 {
889 if constexpr (I > 0)
890 {
891 if (std::get<I - 1>(it_) != std::get<I - 1>(b.it_))
892 return false;
893 return equal< I - 1>(b);
894 }
895 else
896 {
897 return true;
898 }
899 }
900
901 template< std::size_t I>
902 void increment() noexcept
903 {
904 auto&& iti = std::get<I - 1>(it_);
905 ++iti;
906 if constexpr (I > 1)
907 {
908 auto&& rngi = rng().template get<I - 1>();
909 if (iti != rngi.end())
910 return;
911 iti = rngi.begin();
912 increment< I - 1>();
913 }
914 }
915
916 const range_class< TL...>& rng() const
917 {
918 return *rngp_;
919 }
920 const range_class< TL...>* rngp_;
921 std::tuple< iterator_class< selector<TL>> ...> it_;
922 };
924
932 template< tag ... TL>
933 class range_class : public impl::range_base {
934 public:
935 range_class() noexcept
936 {}
937 range_class(const range_class< TL> & ... vl) noexcept requires (sizeof...(TL) > 0)
938 : i_(vl ...)
939 {}
941 template< tag ... TL2>
942 requires (sizeof...(TL2) >= sizeof...(TL))
943 explicit range_class(const range_class< TL2...> & r) noexcept
944 : i_(r.template get<selector<TL>>() ...)
945 {}
951 std::size_t size() const
952 {
953 return (1 * ... * get< TL>().size());
954 }
955
959 iterator_class<TL ...> begin() const noexcept
960 {
961 return iterator_class<TL ...>(this, get_begin< TL>() ...);
962 }
963
967 iterator_class<TL ...> end() const noexcept
968 {
969 return iterator_class<TL ...>(this, get_end< TL>() ...);
970 }
971
976 template< typename T>
977 requires impl::one_of< selector<T>, selector<TL> ...>
978 && non_static_tag< pick<selector<T>, TL ...>>
979 auto&& get() const noexcept
980 {
981 return std::get< range_class< pick<selector<T>, TL ...>>>(i_);
982 }
983
988 template< typename T>
989 requires impl::one_of< selector<T>, selector<TL> ...>
990 && static_tag< pick<selector<T>, TL ...>>
991 static constexpr auto get() noexcept
992 {
993 return range_class< pick<selector<T>, TL ...>>{};
994 }
995
1000 template< std::size_t I>
1001 auto&& get() const noexcept
1002 {
1003 return std::get< I>(i_);
1004 }
1005
1006 template< std::size_t I>
1007 using get_tag = std::tuple_element_t<I, std::tuple<TL ...>>;
1009 private:
1010 template< tag T>
1011 auto get_begin() const noexcept
1012 {
1013 auto&& rngi = std::get< range_class< T>>(i_);
1014 return rngi.begin();
1015 }
1016 template< tag T>
1017 auto get_end() const noexcept
1018 {
1019 auto&& rngi = std::get< range_class< T>>(i_);
1020 if constexpr (impl::position_of<T, TL ...> == 0)
1021 return rngi.end();
1022 else
1023 return rngi.begin();
1024 }
1025 using i_type = std::tuple< range_class< TL> ...>;
1026 i_type i_;
1027 };
1028
1037 template< tag ... TL1, tag ... TL2>
1038 range_class< TL1 ..., TL2 ...> operator&(const range_class< TL1 ...>& rnga, const range_class< TL2 ...>& rngb)
1039 {
1040 return range_class< TL1 ..., TL2 ...>(rnga.template get< TL1>() ..., rngb.template get< TL2>() ...);
1041 }
1042
1043 struct rp_dense {
1044 constexpr static std::size_t roundup(std::size_t s)
1045 {
1046 return s;
1047 }
1048 };
1049
1050 struct rp_odd {
1051 constexpr static std::size_t roundup(std::size_t s)
1052 {
1053 return s | 1;
1054 }
1055 };
1056
1058 namespace impl {
1059
1060 template< tag T>
1061 inline constexpr std::size_t physical_roundup(std::size_t s)
1062 {
1063 return T::roundup_policy::roundup(s);
1064 }
1065
1066 template< tag T>
1067 struct size_traits
1068 {
1069 static constexpr std::size_t static_multiplier = 1;
1070 static constexpr bool has_dynamic_multiplier = true;
1071 template< typename T2>
1072 static std::size_t dynamic_multiplier(T2&& r)
1073 {
1074 return physical_roundup<T>(r.template get<selector<T>>().size());
1075 }
1076 };
1077
1078 template< tag T>
1079 requires T::is_static
1080 struct size_traits<T>
1081 {
1082 static constexpr std::size_t static_multiplier = physical_roundup<T>(T::end - T::begin);
1083 static constexpr bool has_dynamic_multiplier = false;
1084 };
1085
1086 template< tag T>
1087 class multiplier_class
1088 {
1089 public:
1090 multiplier_class()
1091 : value_(0)
1092 {}
1093 explicit multiplier_class(std::size_t v)
1094 : value_(v)
1095 {}
1096 void assign_value(std::size_t v)
1097 {
1098 value_ = v;
1099 }
1100 std::size_t value() const
1101 {
1102 return value_;
1103 }
1104 private:
1105 std::size_t value_;
1106 };
1107
1108 template< tag T, std::size_t s>
1109 struct sm_tag
1110 {
1111 static constexpr bool is_tag = true;
1112 static constexpr bool is_direct = false;
1113 using core = sm_tag< T, s>;
1114 static constexpr bool is_selector = false;
1115 using selector = T;
1116 template<selector_tag T2>
1117 using retag = sm_tag< T2, s>;
1118 template<typename RP2>
1119 using set_roundup = void;
1120
1121 static constexpr bool has_static_multiplier = true;
1122 static constexpr std::size_t static_multiplier = s;
1123 };
1124
1125 template< tag T, std::size_t b, std::size_t e, std::size_t s>
1126 struct srm_tag
1127 {
1128 static constexpr bool is_tag = true;
1129 static constexpr bool is_direct = false;
1130 using core = sm_tag< T, s>;
1131 static constexpr bool is_selector = false;
1132 using selector = T;
1133 template<selector_tag T2>
1134 using retag = sm_tag< T2, s>;
1135 template<typename RP2>
1136 using set_roundup = void;
1137
1138 static constexpr bool is_static = true;
1139 static constexpr std::size_t begin = b;
1140 static constexpr std::size_t end = e;
1141
1142 static constexpr bool has_static_multiplier = true;
1143 static constexpr std::size_t static_multiplier = s;
1144 };
1145
1146 template< typename T>
1147 concept has_static_multiplier = requires {
1148 requires tag<T>;
1149 {T::has_static_multiplier} -> std::convertible_to<bool>;
1150 requires T::has_static_multiplier;
1151 };
1152
1153 template< tag T, std::size_t s>
1154 class multiplier_class<sm_tag<T, s>>
1155 {
1156 public:
1157 multiplier_class()
1158 {}
1159 static constexpr std::size_t value()
1160 {
1161 return s;
1162 }
1163 };
1164
1165 template< tag ... TL>
1166 struct multiplier_list_traits;
1167
1168 template<>
1169 struct multiplier_list_traits<>
1170 {
1171 static constexpr std::size_t static_multiplier = 1;
1172 using multiplier_tag_list = tag_list<>;
1173 static constexpr bool has_dynamic_multiplier = false;
1174 };
1175
1176 template< tag T0, tag ... TL>
1177 requires (!multiplier_list_traits< TL ...>::has_dynamic_multiplier)
1178 struct multiplier_list_traits< T0, TL ...>
1179 {
1180 private:
1181 using head_traits = size_traits<T0>;
1182 using tail_traits = multiplier_list_traits< TL ...>;
1183 public:
1184 static constexpr std::size_t static_multiplier = head_traits::static_multiplier * tail_traits::static_multiplier;
1185 private:
1186 using head_multiplier_tag = sm_tag<selector<T0>, tail_traits::static_multiplier>;
1187 using tail_multiplier_tag_list = typename tail_traits::multiplier_tag_list;
1188 public:
1189 using multiplier_tag_list = concat_list< head_multiplier_tag, tail_multiplier_tag_list>;
1190 static constexpr bool has_dynamic_multiplier = head_traits::has_dynamic_multiplier;
1191 template< tag ... TL2, tag ... TL3>
1192 static std::size_t fill_dynamic_multiplier(std::tuple< multiplier_class< TL2>...>&, const range_class<TL3 ...>& r)
1193 requires has_dynamic_multiplier
1194 {
1195 return head_traits::dynamic_multiplier(r);
1196 }
1197 };
1198
1199 template< tag T0, tag ... TL>
1200 requires multiplier_list_traits< TL ...>::has_dynamic_multiplier
1201 struct multiplier_list_traits< T0, TL ...>
1202 {
1203 private:
1204 using head_traits = size_traits<T0>;
1205 using tail_traits = multiplier_list_traits< TL ...>;
1206 public:
1207 static constexpr std::size_t static_multiplier = head_traits::static_multiplier * tail_traits::static_multiplier;
1208 private:
1209 using head_multiplier_tag = selector<T0>;
1210 using tail_multiplier_tag_list = typename tail_traits::multiplier_tag_list;
1211 public:
1212 using multiplier_tag_list = concat_list< head_multiplier_tag, tail_multiplier_tag_list>;
1213 static constexpr bool has_dynamic_multiplier = true;
1214 template< tag ... TL2, tag ... TL3>
1215 static std::size_t fill_dynamic_multiplier(std::tuple< multiplier_class< TL2>...>& m, const range_class<TL3 ...>& r)
1216 {
1217 std::size_t dm = tail_traits::fill_dynamic_multiplier(m, r);
1218 std::get< multiplier_class<head_multiplier_tag>>(m).assign_value(tail_traits::static_multiplier * dm);
1219 if constexpr (head_traits::has_dynamic_multiplier)
1220 {
1221 dm *= head_traits::dynamic_multiplier(r);
1222 }
1223 return dm;
1224 }
1225 };
1226
1227 template< tag ... TL>
1228 class multiplier_list_class
1229 {
1230 public:
1231 multiplier_list_class()
1232 {}
1233 template< tag ... TL3>
1234 requires (sizeof...(TL3) == sizeof...(TL))
1235 explicit multiplier_list_class(const range_class<TL3 ...>& r)
1236 {
1237 using traits = multiplier_list_traits<pick<selector<TL>, TL3...> ...>;
1238 if constexpr (traits::has_dynamic_multiplier)
1239 {
1240 traits::fill_dynamic_multiplier(m_, r);
1241 }
1242 }
1243 template< tag ... TL3>
1244 requires (sizeof...(TL3) >= sizeof...(TL))
1245 explicit multiplier_list_class(const multiplier_list_class<TL3 ...>& r)
1246 : m_( r.template get<TL>() ...)
1247 {}
1248 template< tag ... TL3, tag ... TL2>
1249 requires same_selector_list<tag_list<TL3...>, tag_list<TL...>>
1250 && subset_selector< tag_list<TL2...>, tag_list<TL...>>
1251 std::size_t flat(const range_class<TL3 ...>& r, const index_class<TL2 ...>& i) const
1252 {
1253 return (0 + ... + flat_one<TL2>(r, i));
1254 }
1255 template< tag T2>
1256 auto&& get() const
1257 {
1258 return std::get< multiplier_class<pick<selector<T2>, TL...>>>(m_);
1259 }
1260 template< std::size_t I2>
1261 auto&& get() const
1262 {
1263 return std::get< I2>(m_);
1264 }
1265 private:
1266 std::tuple< multiplier_class< TL>...> m_;
1267
1268 template< tag T, tag ... TL3, tag ... TL2>
1269 std::size_t flat_one(const range_class<TL3 ...>& r, const index_class<TL2 ...>& i) const
1270 {
1271 auto&& ix = i.template get<selector<T>>();
1272 auto&& rx = r.template get<selector<T>>();
1273
1274 std::size_t mv = std::get< multiplier_class< pick<selector<T>, TL...>>>(m_).value();
1275 std::size_t fv = rx.flat(ix);
1276 return mv * fv;
1277 }
1278 };
1279
1280 template<typename L>
1281 struct multiplier_list_creator;
1282
1283 template<tag ... TL2>
1284 struct multiplier_list_creator< tag_list< TL2 ...>>
1285 {
1286 using type = multiplier_list_class< TL2 ...>;
1287 };
1288
1289 template< tag ... TL3>
1290 using multiplier_list = typename multiplier_list_creator< typename multiplier_list_traits< TL3...>::multiplier_tag_list>::type;
1291
1292 template< tag RT, tag MT>
1293 struct mixer_traits;
1294
1295 template< tag RT, tag MT>
1296 requires same_tag<RT, selector<MT>>
1297 struct mixer_traits<RT, MT>
1298 {
1299 using type = MT;
1300 };
1301
1302 template< tag RT, tag MT>
1303 requires same_tag<selector<RT>, MT>
1304 struct mixer_traits<RT, MT>
1305 {
1306 using type = RT;
1307 };
1308
1309 template< non_static_tag RT, tag MT>
1310 requires MT::has_static_multiplier
1311 struct mixer_traits<RT, MT>
1312 {
1313 using type = sm_tag<selector<RT>, MT::static_multiplier>;
1314 };
1315
1316 template< static_tag RT, tag MT>
1317 requires MT::has_static_multiplier
1318 struct mixer_traits<RT, MT>
1319 {
1320 using type = srm_tag<selector<RT>, RT::begin, RT::end, MT::static_multiplier>;
1321 };
1322
1323 template< typename RC, typename MLC>
1324 struct mixer_list_traits;
1325
1326 template<>
1327 struct mixer_list_traits< range_class<>, multiplier_list_class<>>
1328 {
1329 using type = tag_list<>;
1330 };
1331
1332 template< tag RT, tag ... RL, tag MT, tag ... ML>
1333 requires (sizeof...(RL) == sizeof...(ML))
1334 struct mixer_list_traits< range_class< RT, RL...>, multiplier_list_class< MT, ML...>>
1335 {
1336 private:
1337 using head_traits = mixer_traits< RT, MT>;
1338 using tail_traits = mixer_list_traits< range_class< RL...>, multiplier_list_class< ML...>>;
1339 public:
1340 using type = concat_list< typename head_traits::type, typename tail_traits::type>;
1341 };
1342
1343 template< tag T>
1344 struct range_demixer_traits
1345 {
1346 using type = selector<T>;
1347 };
1348
1349 template< tag T>
1350 requires T::is_static
1351 struct range_demixer_traits<T>
1352 {
1353 using type = sr_tag<selector<T>, T::begin, T::end>;
1354 };
1355
1356 template< tag T>
1357 struct multiplier_demixer_traits
1358 {
1359 using type = selector<T>;
1360 };
1361
1362 template< tag T>
1363 requires T::has_static_multiplier
1364 struct multiplier_demixer_traits<T>
1365 {
1366 using type = sm_tag<selector<T>, T::static_multiplier>;
1367 };
1368 }
1369
1370 template< typename E, tag ... TL>
1371 class tensor_class;
1372
1373 template< typename E, tag ... TL>
1374 class tensor_view;
1375
1376 namespace impl {
1377 template< typename E, typename X>
1378 struct tensor_view_creator;
1379
1380 template< typename E, tag ... TL>
1381 struct tensor_view_creator< E, tag_list< TL...>>
1382 {
1383 using type = tensor_view< E, TL...>;
1384 };
1385 }
1387
1388 template< typename E, tag ... TL>
1390 };
1391
1404 template< typename E, tag ... TL>
1406 private:
1407 using self_ = tensor_view< E, TL...>;
1409 public:
1411 template< tag ... TL3, tag ... TL2>
1412 explicit tensor_view(const range_class< TL3 ...>& rng, const impl::multiplier_list_class< TL2...>& mult, E* data)
1413 : rng_(rng),
1414 mult_(mult),
1415 arr_(data)
1416 {}
1417
1418 self_& operator=(const self_&) = delete;
1419 self_& operator=(self_&&) = delete;
1421
1426 const range_t& range() const
1427 {
1428 return rng_;
1429 }
1430
1441 template< tag ... TL2>
1443 requires (sizeof...(TL2) < sizeof...(TL))
1444 && impl::subset_selector< tag_list< TL2...>, tag_list< TL...>>
1445 {
1446 using result_list = typename impl::subtract_traits<tag_list< TL...>, tag_list< TL2...>>::type;
1447 using result_view = typename impl::tensor_view_creator< E, result_list>::type;
1448 return result_view(rng_, mult_, arr_ + mult_.flat(rng_, i));
1449 }
1450
1457 template< tag ... TL2>
1459 requires (sizeof...(TL2) == sizeof...(TL))
1460 && impl::subset_selector< tag_list< TL2...>, tag_list< TL...>>
1461 {
1462 return arr_[mult_.flat(rng_, i)];
1463 }
1464
1473 E* data() const
1474 requires (sizeof...(TL) == 1) && ((TL::has_static_multiplier) && ...) && ((TL::static_multiplier == 1) && ...)
1475 {
1476 return arr_;
1477 }
1478
1486 E* flat_data() const
1487 {
1488 return arr_;
1489 }
1490
1494 static constexpr std::size_t dimensions = sizeof...(TL);
1495
1501 template< tag T2>
1502 std::size_t dim_size() const
1503 {
1504 return rng_.template get< selector<T2>>().size();
1505 }
1506
1512 template< std::size_t I2>
1513 std::size_t dim_size() const
1514 {
1515 return rng_.template get< I2>().size();
1516 }
1517
1527 template< tag T2>
1528 requires impl::has_static_multiplier< pick< selector<T2>, TL...>>
1529 static constexpr std::size_t dim_multiplier()
1530 {
1531 return pick< selector<T2>, TL...>::static_multiplier;
1532 }
1533
1535 template< tag T2>
1536 requires (!impl::has_static_multiplier< pick< selector<T2>, TL...>>)
1537 std::size_t dim_multiplier() const
1538 {
1539 return mult_.template get< selector<T2>>().value();
1540 }
1542
1552 template< std::size_t I2>
1553 requires impl::has_static_multiplier< pick_index< I2, TL...>>
1554 static constexpr std::size_t dim_multiplier()
1555 {
1556 return pick_index< I2, TL...>::static_multiplier;
1557 }
1558
1560 template< std::size_t I2>
1561 requires (!impl::has_static_multiplier< pick_index< I2, TL...>>)
1562 std::size_t dim_multiplier() const
1563 {
1564 return mult_.template get< I2>().value();
1565 }
1567
1568 static constexpr static_tensor_view< E, TL...> st{};
1569
1570 private:
1571 range_t rng_;
1572 impl::multiplier_list_class< typename impl::multiplier_demixer_traits< TL>::type ...> mult_;
1573 E* arr_;
1574 };
1575
1576 template< tag T2, typename E, tag ... TL>
1577 requires impl::has_static_multiplier< pick< selector<T2>, TL...>>
1578 inline constexpr std::size_t dim_multiplier(static_tensor_view<E, TL...>)
1579 {
1580 return tensor_view<E, TL...>::template dim_multiplier< T2>();
1581 }
1582
1583 template< std::size_t I2, typename E, tag ... TL>
1584 requires (!impl::has_static_multiplier< pick_index< I2, TL...>>)
1585 inline constexpr std::size_t dim_multiplier(static_tensor_view<E, TL...>)
1586 {
1587 return tensor_view<E, TL...>::template dim_multiplier< I2>();
1588 }
1589
1596 template< typename E, tag ... TL>
1597 using extract_tensor_view = typename impl::tensor_view_creator< E, typename impl::mixer_list_traits< range_class< TL...>, impl::multiplier_list< TL...>>::type>::type;
1598
1616 template< typename E, tag ... TL>
1617 class tensor_class {
1618 public:
1619 tensor_class() noexcept
1620 {}
1627 template< tag ... TL2>
1628 requires (sizeof...(TL2) == sizeof...(TL))
1630 : rng_(rng),
1631 mult_( rng),
1632 arr_(physical_size(rng))
1633 {}
1634
1641 template< tag ... TL2>
1642 requires (sizeof...(TL2) == sizeof...(TL))
1643 tensor_class(const range_class< TL2 ...>& rng, const E& e) noexcept
1644 : rng_(rng),
1645 mult_(rng),
1646 arr_(physical_size(rng), e)
1647 {}
1648
1649 using view_type = extract_tensor_view< E, TL ...>;
1650 using const_view_type = extract_tensor_view< const E, TL ...>;
1651
1656 view_type view()
1657 {
1658 return view_type(rng_, mult_, arr_.data());
1659 }
1660
1665 const_view_type view() const
1666 {
1667 return const_view_type(rng_, mult_, arr_.data());
1668 }
1669
1680 template< tag ... TL2>
1682 requires (sizeof...(TL2) < sizeof...(TL))
1683 && impl::subset_selector< tag_list< TL2...>, tag_list< TL...>>
1684 {
1685 return view()[i];
1686 }
1687
1698 template< tag ... TL2>
1700 requires (sizeof...(TL2) < sizeof...(TL))
1701 && impl::subset_selector< tag_list< TL2...>, tag_list< TL...>>
1702 {
1703 return view()[i];
1704 }
1705
1710 const range_class< TL ...>& range() const
1711 {
1712 return rng_;
1713 }
1714
1721 template< tag ... TL2>
1723 requires (sizeof...(TL2) == sizeof...(TL))
1724 && impl::subset_selector< tag_list< TL2...>, tag_list< TL...>>
1725 {
1726 return arr_[mult_.flat(rng_, i)];
1727 }
1728
1735 template< tag ... TL2>
1736 const E& operator[](const index_class< TL2...>& i) const
1737 requires (sizeof...(TL2) == sizeof...(TL))
1738 && impl::subset_selector< tag_list< TL2...>, tag_list< TL...>>
1739 {
1740 return arr_[mult_.flat(rng_, i)];
1741 }
1742
1749 E* data()
1750 requires (sizeof...(TL) == 1)
1751 {
1752 return arr_.data();
1753 }
1754
1761 const E* data() const
1762 requires (sizeof...(TL) == 1)
1763 {
1764 return arr_.data();
1765 }
1766
1774 {
1775 return arr_.data();
1776 }
1777
1784 const E* flat_data() const
1785 {
1786 return arr_.data();
1787 }
1788
1789 std::size_t flat_size() const
1790 {
1791 return arr_.size();
1792 }
1793
1794 template< tag ... TL2>
1795 requires (sizeof...(TL2) == sizeof...(TL))
1796 static std::size_t physical_size(const range_class< TL2 ...>& rng)
1797 {
1798 return (1 * ... * impl::physical_roundup<TL>(rng.template get<TL2>().size()));
1799 }
1800 private:
1801 range_class< TL ...> rng_;
1802 impl::multiplier_list< TL ...> mult_;
1803 std::vector< E> arr_;
1804 };
1805
1807 namespace impl {
1808 template< typename P, typename C>
1809 struct permute;
1810
1811 template< typename ... SL, typename C>
1812 struct permute< tag_list< SL...>, C>
1813 {
1814 using type = typename C::template type< SL...>;
1815 };
1816
1817 template< typename P, typename C>
1818 using permute_t = typename permute< P, C>::type;
1819
1820 template< typename E, tag ... TL>
1821 struct permutator_tensor_class
1822 {
1823 template< typename ... SL>
1824 using type = tensor_class< E, pick<selector<SL>, TL...> ...>;
1825 };
1826
1827 template< tag ... TL>
1828 struct permutator_range_class
1829 {
1830 template< typename ... SL>
1831 using type = range_class< pick<SL, TL...> ...>;
1832 };
1833
1834 struct permutator_range
1835 {
1836 template< typename ... SL>
1837 struct type {
1838 template< tag ... TL>
1839 static auto permute_range(const range_class<TL...>& r)
1840 {
1841 using range = range_class< pick<SL, TL...> ...>;
1842 return range((r.template get<SL>() & ...));
1843 }
1844 };
1845 };
1846 }
1848
1856 template< typename P, typename E, tag ... TL>
1857 using permute_tensor_class = impl::permute_t< P, impl::permutator_tensor_class<E, TL...>>;
1858
1860 template< typename P, tag ... TL>
1861 using permute_range_class = impl::permute_t< P, impl::permutator_range_class<TL...>>;
1862
1863 template< typename P, tag ... TL>
1864 auto permute_range(const range_class<TL...>& r)
1865 {
1866 using permutator = impl::permute_t<P, impl::permutator_range>;
1867 return permutator::permute_range(r);
1868 }
1870
1871 // CO
1872
1874 namespace impl {
1875 template< selector_tag T>
1876 struct c {
1877 static constexpr bool is_tag = true;
1878 static constexpr bool is_direct = false;
1879 using core = c<T>;
1880 static constexpr bool is_selector = true;
1881 using selector = c<T>;
1882 template<selector_tag T2>
1883 using retag = T2;
1884 template<typename RP2>
1885 using set_roundup = void;
1886 };
1887
1888 template< selector_tag T>
1889 struct co_traits {
1890 using co = c< T>;
1891 };
1892
1893 template< selector_tag T>
1894 struct co_traits< c<T>> {
1895 using co = T;
1896 };
1897 }
1899
1910 template< tag T>
1911 using co = retag< typename impl::co_traits<selector<T>>::co, T>;
1912
1914 namespace impl {
1915 template< typename X>
1916 struct co_list_traits;
1917
1918 template< tag ... TL>
1919 struct co_list_traits< tag_list<TL ...>> {
1920 using co_list = tag_list<co<TL>...>;
1921 };
1922 }
1924
1929 template< typename X>
1930 using co_list = typename impl::co_list_traits< X>::co_list;
1931
1938 template< tag T>
1939 inline constexpr range_class<co<T>> operator~(const range_class<T>& r)
1940 {
1941 return range_class<co<T>>(r.template retag<co<T>>());
1942 }
1943
1950 template< tag T>
1952 {
1953 return index_class<co<T>>(r.template retag<co<T>>());
1954 }
1955
1957
1958 template< typename E, tagged::tag STL0, tagged::tag DTL0>
1959 inline void permute_tensor(const tagged::tensor_view< const E, STL0>& svec, const tagged::tensor_view< E, DTL0>& dvec)
1960 {
1961 auto r0 = dvec.range().template get<DTL0>();
1962 for (auto i0 : r0)
1963 {
1964 dvec[i0] = svec[i0];
1965 }
1966 }
1967
1968 template< typename E, tagged::tag ... STL, tagged::tag DTL0, tagged::tag ... DTL>
1969 inline void permute_tensor(const tagged::tensor_view< const E, STL ...>& svec, const tagged::tensor_view< E, DTL0, DTL ...>& dvec)
1970 {
1971 auto r0 = dvec.range().template get<DTL0>();
1972 for (auto i0 : r0)
1973 {
1974 auto sslice = svec[i0];
1975 auto dslice = dvec[i0];
1976
1977 permute_tensor(sslice, dslice);
1978 }
1979 }
1980
1981 template< typename E, tagged::tag ... STL, tagged::tag ... DTL>
1982 requires (sizeof...(STL) == sizeof...(DTL))
1983 inline void permute_tensor(const tagged::tensor_class< E, STL ...>& svec, tagged::tensor_class< E, DTL ...>& dvec)
1984 {
1985 permute_tensor(svec.view(), dvec.view());
1986 }
1987
1988}
1989
1990#endif
A list of tagged indexes (a position in an N-dimensional space)
Definition tagged.hpp:784
auto && get() const noexcept
Retrieve individual tagged index by selector tag.
Definition tagged.hpp:812
auto && get() const noexcept
Retrieve individual tagged index by zero-based position.
Definition tagged.hpp:802
A list of tagged ranges (an N-dimensional box)
Definition tagged.hpp:933
iterator_class< TL ... > begin() const noexcept
Lexicographical iterator through the N-dimensional box.
Definition tagged.hpp:959
std::size_t size() const
Size (volume) of the range.
Definition tagged.hpp:951
auto && get() const noexcept
Retrieve individual range by selector tag.
Definition tagged.hpp:979
iterator_class< TL ... > end() const noexcept
Lexicographical iterator through the N-dimensional box.
Definition tagged.hpp:967
static constexpr auto get() noexcept
Retrieve individual range by selector tag.
Definition tagged.hpp:991
auto && get() const noexcept
Retrieve individual range by index.
Definition tagged.hpp:1001
Definition tagged.hpp:408
A tensor - a multi-dimensional tagged generalization of vector/matrix.
Definition tagged.hpp:1617
const E * flat_data() const
A const pointer to the beginning of the array containing the data.
Definition tagged.hpp:1784
auto operator[](const index_class< TL2 ... > &i) const
Extract an immutable reference to a sub-space of this tensor.
Definition tagged.hpp:1699
E & operator[](const index_class< TL2... > &i)
Access an element of this tensor.
Definition tagged.hpp:1722
const_view_type view() const
Return tensor_view acting as a const reference to the complete tensor_class.
Definition tagged.hpp:1665
E * data()
A pointer to the beginning of the array containing the data.
Definition tagged.hpp:1749
auto operator[](const index_class< TL2 ... > &i)
Extract a reference to a sub-space of this tensor.
Definition tagged.hpp:1681
const range_class< TL ... > & range() const
The range corresponding to this tensor.
Definition tagged.hpp:1710
const E & operator[](const index_class< TL2... > &i) const
Read an element of this tensor.
Definition tagged.hpp:1736
view_type view()
Return tensor_view acting as a reference to the complete tensor_class.
Definition tagged.hpp:1656
E * flat_data()
A pointer to the beginning of the array containing the data.
Definition tagged.hpp:1773
tensor_class(const range_class< TL2 ... > &rng, const E &e) noexcept
Initialize the tensor_class to a size defined by a range_class.
Definition tagged.hpp:1643
tensor_class(const range_class< TL2 ... > &rng)
Initialize the tensor_class to a size defined by a range_class.
Definition tagged.hpp:1629
const E * data() const
A const pointer to the beginning of the array containing the data.
Definition tagged.hpp:1761
A reference to a sub-space of a tensor.
Definition tagged.hpp:1405
auto operator[](const index_class< TL2 ... > &i) const
Extract a sub-space of this sub-space.
Definition tagged.hpp:1442
E * flat_data() const
A pointer to the element at the position defined by the lowermost index values of all dimensions of t...
Definition tagged.hpp:1486
const range_t & range() const
The range corresponding to the sub-space.
Definition tagged.hpp:1426
E & operator[](const index_class< TL2 ... > &i) const
Access an element of this sub-space.
Definition tagged.hpp:1458
E * data() const
A pointer to the beginning of the array containing the sub-space data.
Definition tagged.hpp:1473
static constexpr std::size_t dim_multiplier()
Return the multiplier associated with the dimension specified by a tag.
Definition tagged.hpp:1529
static constexpr std::size_t dimensions
Definition tagged.hpp:1494
static constexpr std::size_t dim_multiplier()
Return the multiplier associated with the dimension specified by an index.
Definition tagged.hpp:1554
std::size_t dim_size() const
Return the sub-space size in a dimension specified by a tag.
Definition tagged.hpp:1502
A bare tag used to select a dimension.
Definition tagged.hpp:36
Any tag used to specify a dimension.
Definition tagged.hpp:28
typename impl::tag_traits< T >::selector selector
Extract selector tag from any tag.
Definition tagged.hpp:43
typename impl::co_list_traits< X >::co_list co_list
Co-tag every element of a tag_list.
Definition tagged.hpp:1930
typename impl::tensor_view_creator< E, typename impl::mixer_list_traits< range_class< TL... >, impl::multiplier_list< TL... > >::type >::type extract_tensor_view
The type of a tensor_view acting as a reference to the complete tensor_class with the given tag list.
Definition tagged.hpp:1597
index_class< TL1 ..., TL2 ... > operator&(const index_class< TL1 ... > &ia, const index_class< TL2 ... > &ib)
Concatenate two (multi-dimensional) indexes together.
Definition tagged.hpp:838
retag< typename impl::co_traits< selector< T > >::co, T > co
Provide a co-tag for a given tag.
Definition tagged.hpp:1911
impl::permute_t< P, impl::permutator_tensor_class< E, TL... > > permute_tensor_class
Provide a tensor_class for the selected dimensions with layout specified by a tagged::tag_list.
Definition tagged.hpp:1857
constexpr range_class< co< T > > operator~(const range_class< T > &r)
Return a co-tagged range with the same extent.
Definition tagged.hpp:1939
Definition tagged.hpp:1043
Definition tagged.hpp:1050
Definition tagged.hpp:1389
A wrapped list of tags.
Definition tagged.hpp:228