28 concept tag = impl::tag_traits<T>::is_tag;
43 using selector =
typename impl::tag_traits<T>::selector;
46 template<
typename T1,
typename T2>
47 concept same_selector = std::same_as< selector<T1>,
selector<T2>>;
51 template< tag T, std::
size_t b, std::
size_t e,
typename RP>
54 template< tag T, std::
size_t b, std::
size_t e>
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;
61 template<selector_tag T2>
62 using retag = sr_tag< T2, b, e>;
64 using set_roundup = srr_tag<T, b, e, RP>;
66 static constexpr bool is_static =
true;
67 static constexpr std::size_t begin = b;
68 static constexpr std::size_t end = e;
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;
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>;
83 template< tag T,
typename RP>
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;
90 template<selector_tag T2>
91 using retag = r_tag< T2, RP>;
93 static constexpr bool has_roundup =
true;
94 using roundup_policy = RP;
95 template<
typename RP2>
96 using set_roundup = r_tag< T, RP2>;
100 template<
typename T>
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>;
115 template<
typename T>
116 requires std::derived_from<T, tag_base>
119 static constexpr bool is_tag =
true;
120 static constexpr bool is_direct =
true;
122 static constexpr bool is_selector =
true;
124 template<selector_tag T2>
126 template<
typename RP>
127 using set_roundup = r_tag<T, RP>;
132 using core =
typename impl::tag_traits<T>::core;
134 template<
typename T1,
typename T2>
135 concept same_tag = std::same_as< core<T1>, core<T2>>;
137 template< selector_tag T2, tag T>
138 using retag =
typename impl::tag_traits<T>::template retag<T2>;
140 template< tag T,
typename RP>
141 using set_roundup =
typename impl::tag_traits<T>::template set_roundup<RP>;
143 template<
typename T>
144 concept static_tag =
tag<T> && T::is_static;
146 template<
typename T>
147 concept non_static_tag =
tag<T> && (!static_tag<T>);
149 template< static_tag T1, static_tag T2>
150 inline constexpr bool same_static_range = T1::begin == T2::begin && T1::end == T2::end;
155 using index_carrier_type = std::size_t;
159 template<
tag ... TL>
162 template<
tag ... TL>
163 class iterator_class;
165 template< tag T, std::
size_t D>
168 template<
tag ... TL>
171 template<
typename E,
tag ... TL>
177 struct range_base {};
180 template<
typename T>
181 concept is_range = std::derived_from< T, impl::range_base>;
184 struct index_base {};
186 template< tag T, tag ... TL>
187 struct element_traits;
190 struct element_traits< T> : std::false_type {};
192 template< tag T, tag T2, tag ... TL>
193 requires same_selector<T, T2>
194 struct element_traits< T, T2, TL ...> : std::true_type {};
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 ...> {};
200 template<
typename T,
typename ... TL>
201 concept one_of = element_traits< T, TL...>::value;
203 template< tag T, tag ... TL>
204 struct position_traits;
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>
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>
218 template<
typename T,
typename ... TL>
219 inline constexpr std::size_t position_of = position_traits< T, TL...>::value;
227 template<
typename ... TL>
232 template<
typename TA,
typename TB>
233 struct concat_traits;
235 template< tag TA, tag TB>
236 struct concat_traits< TA, TB> {
240 template< tag TA, tag ... LB>
241 struct concat_traits< TA, tag_list< LB ...>> {
242 using type = tag_list< TA, LB ...>;
245 template<
typename TA,
typename TB>
246 using concat_list =
typename concat_traits< TA, TB>::type;
248 template<
typename LA,
typename LB>
249 struct subtract_traits;
251 template< tag ... TLA>
252 struct subtract_traits< tag_list<TLA...>, tag_list<>> {
253 using type = tag_list<TLA...>;
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>>
260 using type = tag_list<TLA ...>;
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>>
268 using removed_a =
typename subtract_traits< tag_list<TLA ...>, tag_list<TB>>::type;
270 using type = concat_list< TA, removed_a>;
273 template< tag ... TLA, tag TB, tag ... TLB>
274 struct subtract_traits< tag_list<TLA...>, tag_list<TB, TLB...>>
277 using removed_a =
typename subtract_traits<tag_list<TLA...>, tag_list<TB>>::type;
279 using type =
typename subtract_traits<removed_a, tag_list<TLB ...>>::type;
282 template< selector_tag T, tag ... TL>
285 template< selector_tag T, tag T0, tag ... TL>
286 requires same_selector<T, T0>
287 struct pick_traits< T, T0, TL ...>
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 ...>
298 template< std::size_t I, tag ... TL>
299 struct pick_index_traits;
301 template< tag T0, tag ... TL>
302 struct pick_index_traits< 0, T0, TL ...>
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 ...>
312 template<
typename A,
typename B>
313 struct same_list_traits;
315 template< tag ... AL, tag ... BL>
316 requires (
sizeof...(AL) ==
sizeof...(BL))
317 struct same_list_traits< tag_list<AL...>, tag_list<BL...>>
319 static constexpr bool value = (same_selector<AL, BL> && ...);
322 template<
typename A,
typename B>
323 concept same_selector_list = same_list_traits< A, B>::value;
325 template<
typename A,
typename B>
326 struct subset_traits;
328 template< tag ... AL, tag ... BL>
329 struct subset_traits< tag_list<AL...>, tag_list<BL...>>
331 static constexpr bool value = (one_of<AL, BL...> && ...);
334 template<
typename A,
typename B>
335 concept subset_selector = subset_traits< A, B>::value;
338 template<
typename T,
typename ... TL>
339 requires impl::one_of<T, TL...>
340 using pick =
typename impl::pick_traits< T, TL...>::type;
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;
354 class index_class< T> :
public impl::index_base {
356 index_class() noexcept
359 constexpr explicit index_class(index_carrier_type< T> v) noexcept
363 index_class< T2> retag()
const
365 return index_class< T2>(i_);
367 index_carrier_type<T> value()
const noexcept
371 template< std::
size_t I>
373 auto&&
get()
const noexcept
375 return std::get< I>(i_);
377 template< same_selector<T> T2>
378 auto&&
get()
const noexcept
383 index_carrier_type< T> i_;
395 bool operator==(index_class<T> a, index_class<T> b)
397 return a.value() == b.value();
403 return a.value() != b.value();
407 template< tag T, index_carrier_type<T> D>
410 template< tag T, index_carrier_type<T> E>
411 class static_sentinel_class {
413 using difference_type = std::make_signed_t<index_carrier_type<T>>;
415 static_sentinel_class()
noexcept
419 bool operator==(
const iterator_class<T>& b)
const noexcept
423 bool operator!=(
const iterator_class<T>& b)
const noexcept
428 template<index_carrier_type<T> D>
433 template<index_carrier_type<T> D>
442 class iterator_class< T> {
444 iterator_class() noexcept
447 explicit iterator_class(index_carrier_type< T> v) noexcept
450 template<index_carrier_type<T> E>
451 iterator_class(
const static_sentinel_class<T, E>& b) noexcept
455 index_class< T> operator*() const noexcept
457 return index_class< T>(v_);
459 bool operator==(
const iterator_class<T>& b)
const noexcept
463 bool operator!=(
const iterator_class<T>& b)
const noexcept
467 template<index_carrier_type<T> E>
468 bool operator==(
const static_sentinel_class<T, E>& b)
const noexcept
472 template<index_carrier_type<T> E>
473 bool operator!=(
const static_sentinel_class<T, E>& b)
const noexcept
477 iterator_class<T>& operator++() noexcept
482 iterator_class<T> operator++(
int)
noexcept
489 index_carrier_type< T> v_;
491 template< tag T2, index_carrier_type<T2> E>
492 friend class static_sentinel_class;
495 template< tag T, index_carrier_type<T> D>
498 using difference_type = std::make_signed_t<index_carrier_type<T>>;
500 strided_iterator_class() noexcept
504 explicit strided_iterator_class(index_carrier_type< T> v) noexcept
508 template<index_carrier_type<T> E>
509 strided_iterator_class(
const static_sentinel_class<T, E>& b) noexcept
513 index_class< T> operator*() const noexcept
515 return index_class< T>(v_);
517 bool operator==(
const strided_iterator_class<T, D>& b)
const noexcept
521 bool operator!=(
const strided_iterator_class<T, D>& b)
const noexcept
525 template<index_carrier_type<T> E>
526 bool operator==(
const static_sentinel_class<T, E>& b)
const noexcept
530 template<index_carrier_type<T> E>
531 bool operator!=(
const static_sentinel_class<T, E>& b)
const noexcept
535 strided_iterator_class<T, D>& operator++() noexcept
540 strided_iterator_class<T, D> operator++(
int)
noexcept
547 index_carrier_type< T> v_;
549 template< tag T2, index_carrier_type<T> E>
550 friend class static_sentinel_class;
564 template< non_static_tag T>
565 class range_class< T> :
public impl::range_base {
569 range_class() noexcept
572 explicit range_class(index_carrier_type< T> e) noexcept
575 range_class(index_carrier_type< T> b, index_carrier_type< T> e) noexcept
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
586 range_class<T>& operator=(range_class<T>&& b)
noexcept
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())
599 template<
typename T2>
600 requires same_tag<T, T2>
601 bool operator==(
const range_class<T2>& b)
const
603 return b_ == b.begin_value() && e_ == b.end_value();
605 template<
typename T2>
606 requires same_tag<T, T2>
607 bool operator!=(
const range_class<T2>& b)
const
609 return b_ != b.begin_value() || e_ != b.end_value();
612 range_class< T2> retag()
const
614 return range_class< T2>(b_, e_);
616 template<
typename T2>
617 requires same_selector<T, T2>
620 return i.value() - b_;
622 index_carrier_type<T>
size()
const
626 template<std::
size_t S>
628 auto perfectly_strided()
const
630 if ((e_ - b_) % S != 0)
632 throw std::logic_error(
"range is not perfectly strided");
635 return std::ranges::subrange<strided_iterator>(
636 strided_iterator(b_),
637 strided_iterator(e_));
639 iterator_class<selector>
begin()
const noexcept
641 return iterator_class<selector>(b_);
643 iterator_class<selector>
end()
const noexcept
645 return iterator_class<selector>(e_);
647 index_carrier_type<T> begin_value()
const noexcept
651 index_carrier_type<T> end_value()
const noexcept
655 template< same_selector< T> T2>
656 auto&&
get()
const noexcept
660 template< std::
size_t I>
662 auto&&
get()
const noexcept
666 template< std::
size_t I>
670 index_carrier_type< T> b_, e_;
674 template< static_tag T>
681 constexpr explicit range_class(index_carrier_type< T> e)
683 if (0 != T::begin || e != T::end)
685 throw std::logic_error(
"WTF");
688 constexpr range_class(index_carrier_type< T> b, index_carrier_type< T> e)
690 if (b != T::begin || e != T::end)
692 throw std::logic_error(
"WTF");
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
700 template<
typename T2>
701 requires same_selector<T, T2>
702 constexpr bool operator==(
const range_class<T2>&)
const
704 return same_static_range<T, T2>;
706 template<
typename T2>
707 requires same_selector<T, T2>
708 constexpr bool operator!=(
const range_class<T2>&)
const
710 return !same_static_range<T, T2>;
712 template< static_tag T2>
713 static constexpr range_class< T2> retag()
715 return range_class< T2>();
717 static index_carrier_type<T> flat(
const index_class< selector>& i)
719 return i.value() - T::begin;
721 static constexpr index_carrier_type<T>
size()
723 return T::end - T::begin;
725 template<std::
size_t S>
727 auto perfectly_strided()
const
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),
736 static iterator_class<selector>
begin() noexcept
738 return iterator_class<selector>(T::begin);
740 static static_sentinel_class<selector, T::end>
end() noexcept
742 return static_sentinel_class<selector, T::end>();
744 static constexpr index_carrier_type<T> begin_value() noexcept
748 static constexpr index_carrier_type<T> end_value() noexcept
752 template< same_selector< T> T2>
753 static constexpr auto get() noexcept
755 return range_class<T>{};
757 template< std::
size_t I>
759 auto&&
get()
const noexcept
763 template< std::
size_t I>
769 template<std::
size_t S, tag T>
773 return r.template perfectly_strided<S>();
783 template<
tag ... TL>
784 class index_class :
public impl::index_base {
786 index_class() noexcept
787 : i_(index_carrier_type< TL>(0) ...)
789 constexpr index_class(index_carrier_type< TL> ... vl) noexcept
790 : i_(index_class< TL>(vl) ...)
792 index_class(index_class< TL> ... vl) noexcept
800 template< std::
size_t I>
801 requires (I <
sizeof...(TL))
802 auto&&
get()
const noexcept
804 return std::get< I>(i_);
811 template< impl::one_of< TL ...> T>
812 auto&&
get() const noexcept
814 return std::get< index_class< pick<selector<T>, TL...>>>(i_);
817 std::tuple< index_class< TL> ...> i_;
822 class index_class<> :
public impl::index_base {
824 constexpr index_class() noexcept
837 template<
tag ... TL1,
tag ... TL2>
840 return index_class< TL1 ..., TL2 ...>(ia.template get< TL1>() ..., ib.template get< TL2>() ...);
844 template< tag T1, tag ... TL2>
845 std::ostream& operator<<(std::ostream& o, index_class<T1, TL2 ...> v)
847 ((o <<
"[" << v.template get<T1>()), ..., (o <<
"," << v.template get<TL2>())), o <<
"]";
853 template<
tag ... TL>
854 class iterator_class {
856 iterator_class() noexcept
857 : rngp_(
nullptr), it_(iterator_class< TL>(0) ...)
859 iterator_class(
const range_class< TL...>* rngp, iterator_class< selector<TL>> ... v) noexcept
860 : rngp_(rngp), it_(v ...)
862 index_class< selector<TL> ...> operator*() const noexcept
864 return index_class< selector<TL> ...>(*std::get< iterator_class< selector< TL>>>(it_)...);
866 bool operator==(
const iterator_class<TL ...>& b)
const noexcept
868 return equal<
sizeof...(TL)>(b);
870 bool operator!=(
const iterator_class<TL ...>& b)
const noexcept
872 return !equal<
sizeof...(TL)>(b);
874 iterator_class<TL ...>& operator++() noexcept
876 increment<
sizeof...(TL)>();
879 iterator_class<TL ...> operator++(
int)
noexcept
886 template< std::
size_t I>
887 bool equal(
const iterator_class<TL ...>& b)
const noexcept
891 if (std::get<I - 1>(it_) != std::get<I - 1>(b.it_))
893 return equal< I - 1>(b);
901 template< std::
size_t I>
902 void increment() noexcept
904 auto&& iti = std::get<I - 1>(it_);
908 auto&& rngi = rng().template get<I - 1>();
909 if (iti != rngi.end())
916 const range_class< TL...>& rng()
const
920 const range_class< TL...>* rngp_;
921 std::tuple< iterator_class< selector<TL>> ...> it_;
932 template<
tag ... TL>
933 class range_class :
public impl::range_base {
935 range_class()
noexcept
937 range_class(
const range_class< TL> & ... vl)
noexcept requires (
sizeof...(TL) > 0)
941 template<
tag ... TL2>
942 requires (
sizeof...(TL2) >=
sizeof...(TL))
943 explicit range_class(
const range_class< TL2...> & r) noexcept
959 iterator_class<TL ...>
begin() const noexcept
961 return iterator_class<TL ...>(
this, get_begin< TL>() ...);
967 iterator_class<TL ...>
end() const noexcept
969 return iterator_class<TL ...>(
this, get_end< TL>() ...);
976 template<
typename T>
978 && non_static_tag< pick<selector<T>, TL ...>>
979 auto&&
get() const noexcept
981 return std::get< range_class< pick<selector<T>, TL ...>>>(i_);
988 template<
typename T>
990 && static_tag< pick<selector<T>, TL ...>>
991 static constexpr auto get() noexcept
993 return range_class< pick<selector<T>, TL ...>>{};
1000 template< std::
size_t I>
1003 return std::get< I>(i_);
1006 template< std::
size_t I>
1007 using get_tag = std::tuple_element_t<I, std::tuple<TL ...>>;
1011 auto get_begin() const noexcept
1013 auto&& rngi = std::get< range_class< T>>(i_);
1014 return rngi.begin();
1017 auto get_end() const noexcept
1019 auto&& rngi = std::get< range_class< T>>(i_);
1020 if constexpr (impl::position_of<T, TL ...> == 0)
1023 return rngi.begin();
1025 using i_type = std::tuple< range_class< TL> ...>;
1037 template<
tag ... TL1,
tag ... TL2>
1040 return range_class< TL1 ..., TL2 ...>(rnga.template get< TL1>() ..., rngb.template get< TL2>() ...);
1044 constexpr static std::size_t roundup(std::size_t s)
1051 constexpr static std::size_t roundup(std::size_t s)
1061 inline constexpr std::size_t physical_roundup(std::size_t s)
1063 return T::roundup_policy::roundup(s);
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)
1074 return physical_roundup<T>(r.template get<selector<T>>().
size());
1079 requires T::is_static
1080 struct size_traits<T>
1082 static constexpr std::size_t static_multiplier = physical_roundup<T>(T::end - T::begin);
1083 static constexpr bool has_dynamic_multiplier =
false;
1087 class multiplier_class
1093 explicit multiplier_class(std::size_t v)
1096 void assign_value(std::size_t v)
1100 std::size_t value()
const
1108 template< tag T, std::
size_t s>
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;
1116 template<selector_tag T2>
1117 using retag = sm_tag< T2, s>;
1118 template<
typename RP2>
1119 using set_roundup = void;
1121 static constexpr bool has_static_multiplier =
true;
1122 static constexpr std::size_t static_multiplier = s;
1125 template< tag T, std::
size_t b, std::
size_t e, std::
size_t s>
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;
1133 template<selector_tag T2>
1134 using retag = sm_tag< T2, s>;
1135 template<
typename RP2>
1136 using set_roundup = void;
1138 static constexpr bool is_static =
true;
1139 static constexpr std::size_t begin = b;
1140 static constexpr std::size_t end = e;
1142 static constexpr bool has_static_multiplier =
true;
1143 static constexpr std::size_t static_multiplier = s;
1146 template<
typename T>
1147 concept has_static_multiplier =
requires {
1149 {T::has_static_multiplier} -> std::convertible_to<bool>;
1150 requires T::has_static_multiplier;
1153 template< tag T, std::
size_t s>
1154 class multiplier_class<sm_tag<T, s>>
1159 static constexpr std::size_t value()
1165 template< tag ... TL>
1166 struct multiplier_list_traits;
1169 struct multiplier_list_traits<>
1171 static constexpr std::size_t static_multiplier = 1;
1172 using multiplier_tag_list = tag_list<>;
1173 static constexpr bool has_dynamic_multiplier =
false;
1176 template< tag T0, tag ... TL>
1177 requires (!multiplier_list_traits< TL ...>::has_dynamic_multiplier)
1178 struct multiplier_list_traits< T0, TL ...>
1181 using head_traits = size_traits<T0>;
1182 using tail_traits = multiplier_list_traits< TL ...>;
1184 static constexpr std::size_t static_multiplier = head_traits::static_multiplier * tail_traits::static_multiplier;
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;
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
1195 return head_traits::dynamic_multiplier(r);
1199 template< tag T0, tag ... TL>
1200 requires multiplier_list_traits< TL ...>::has_dynamic_multiplier
1201 struct multiplier_list_traits< T0, TL ...>
1204 using head_traits = size_traits<T0>;
1205 using tail_traits = multiplier_list_traits< TL ...>;
1207 static constexpr std::size_t static_multiplier = head_traits::static_multiplier * tail_traits::static_multiplier;
1209 using head_multiplier_tag = selector<T0>;
1210 using tail_multiplier_tag_list =
typename tail_traits::multiplier_tag_list;
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)
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)
1221 dm *= head_traits::dynamic_multiplier(r);
1227 template< tag ... TL>
1228 class multiplier_list_class
1231 multiplier_list_class()
1233 template< tag ... TL3>
1234 requires (
sizeof...(TL3) ==
sizeof...(TL))
1235 explicit multiplier_list_class(
const range_class<TL3 ...>& r)
1237 using traits = multiplier_list_traits<pick<selector<TL>, TL3...> ...>;
1238 if constexpr (traits::has_dynamic_multiplier)
1240 traits::fill_dynamic_multiplier(m_, r);
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>() ...)
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
1253 return (0 + ... + flat_one<TL2>(r, i));
1258 return std::get< multiplier_class<pick<selector<T2>, TL...>>>(m_);
1260 template< std::
size_t I2>
1263 return std::get< I2>(m_);
1266 std::tuple< multiplier_class< TL>...> m_;
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
1271 auto&& ix = i.template get<selector<T>>();
1272 auto&& rx = r.template get<selector<T>>();
1274 std::size_t mv = std::get< multiplier_class< pick<selector<T>, TL...>>>(m_).value();
1275 std::size_t fv = rx.flat(ix);
1280 template<
typename L>
1281 struct multiplier_list_creator;
1283 template<tag ... TL2>
1284 struct multiplier_list_creator< tag_list< TL2 ...>>
1286 using type = multiplier_list_class< TL2 ...>;
1289 template< tag ... TL3>
1290 using multiplier_list =
typename multiplier_list_creator<
typename multiplier_list_traits< TL3...>::multiplier_tag_list>::type;
1292 template< tag RT, tag MT>
1293 struct mixer_traits;
1295 template< tag RT, tag MT>
1296 requires same_tag<RT, selector<MT>>
1297 struct mixer_traits<RT, MT>
1302 template< tag RT, tag MT>
1303 requires same_tag<selector<RT>, MT>
1304 struct mixer_traits<RT, MT>
1309 template< non_static_tag RT, tag MT>
1310 requires MT::has_static_multiplier
1311 struct mixer_traits<RT, MT>
1313 using type = sm_tag<selector<RT>, MT::static_multiplier>;
1316 template< static_tag RT, tag MT>
1317 requires MT::has_static_multiplier
1318 struct mixer_traits<RT, MT>
1320 using type = srm_tag<selector<RT>, RT::begin, RT::end, MT::static_multiplier>;
1323 template<
typename RC,
typename MLC>
1324 struct mixer_list_traits;
1327 struct mixer_list_traits< range_class<>, multiplier_list_class<>>
1329 using type = tag_list<>;
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...>>
1337 using head_traits = mixer_traits< RT, MT>;
1338 using tail_traits = mixer_list_traits< range_class< RL...>, multiplier_list_class< ML...>>;
1340 using type = concat_list< typename head_traits::type, typename tail_traits::type>;
1344 struct range_demixer_traits
1346 using type = selector<T>;
1350 requires T::is_static
1351 struct range_demixer_traits<T>
1353 using type = sr_tag<selector<T>, T::begin, T::end>;
1357 struct multiplier_demixer_traits
1359 using type = selector<T>;
1363 requires T::has_static_multiplier
1364 struct multiplier_demixer_traits<T>
1366 using type = sm_tag<selector<T>, T::static_multiplier>;
1370 template<
typename E,
tag ... TL>
1373 template<
typename E,
tag ... TL>
1377 template<
typename E,
typename X>
1378 struct tensor_view_creator;
1380 template<
typename E, tag ... TL>
1381 struct tensor_view_creator< E, tag_list< TL...>>
1383 using type = tensor_view< E, TL...>;
1388 template<
typename E,
tag ... TL>
1404 template<
typename E,
tag ... TL>
1411 template<
tag ... TL3,
tag ... TL2>
1418 self_& operator=(
const self_&) =
delete;
1419 self_& operator=(self_&&) =
delete;
1441 template<
tag ... TL2>
1443 requires (
sizeof...(TL2) <
sizeof...(TL))
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));
1457 template<
tag ... TL2>
1459 requires (
sizeof...(TL2) ==
sizeof...(TL))
1462 return arr_[mult_.flat(rng_, i)];
1474 requires (sizeof...(TL) == 1) && ((TL::has_static_multiplier) && ...) && ((TL::static_multiplier == 1) && ...)
1504 return rng_.template get< selector<T2>>().size();
1512 template< std::
size_t I2>
1515 return rng_.template get< I2>().size();
1528 requires impl::has_static_multiplier< pick< selector<T2>, TL...>>
1531 return pick< selector<T2>, TL...>::static_multiplier;
1536 requires (!impl::has_static_multiplier< pick< selector<T2>, TL...>>)
1539 return mult_.template get< selector<T2>>().value();
1552 template< std::
size_t I2>
1553 requires impl::has_static_multiplier< pick_index< I2, TL...>>
1556 return pick_index< I2, TL...>::static_multiplier;
1560 template< std::
size_t I2>
1561 requires (!impl::has_static_multiplier< pick_index< I2, TL...>>)
1564 return mult_.template get< I2>().value();
1568 static constexpr static_tensor_view< E, TL...> st{};
1572 impl::multiplier_list_class< typename impl::multiplier_demixer_traits< TL>::type ...> mult_;
1576 template<
tag T2,
typename E,
tag ... TL>
1577 requires impl::has_static_multiplier< pick< selector<T2>, TL...>>
1580 return tensor_view<E, TL...>::template dim_multiplier< T2>();
1583 template< std::size_t I2,
typename E,
tag ... TL>
1584 requires (!impl::has_static_multiplier< pick_index< I2, TL...>>)
1587 return tensor_view<E, TL...>::template dim_multiplier< I2>();
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;
1616 template<
typename E,
tag ... TL>
1617 class tensor_class {
1619 tensor_class()
noexcept
1627 template< tag ... TL2>
1628 requires (
sizeof...(TL2) ==
sizeof...(TL))
1632 arr_(physical_size(rng))
1641 template<
tag ... TL2>
1642 requires (
sizeof...(TL2) ==
sizeof...(TL))
1646 arr_(physical_size(rng), e)
1658 return view_type(rng_, mult_, arr_.data());
1667 return const_view_type(rng_, mult_, arr_.data());
1680 template<
tag ... TL2>
1682 requires (
sizeof...(TL2) <
sizeof...(TL))
1698 template<
tag ... TL2>
1700 requires (
sizeof...(TL2) <
sizeof...(TL))
1721 template<
tag ... TL2>
1723 requires (
sizeof...(TL2) ==
sizeof...(TL))
1726 return arr_[mult_.flat(rng_, i)];
1735 template<
tag ... TL2>
1737 requires (
sizeof...(TL2) ==
sizeof...(TL))
1740 return arr_[mult_.flat(rng_, i)];
1750 requires (
sizeof...(TL) == 1)
1762 requires (sizeof...(TL) == 1)
1789 std::size_t flat_size()
const
1794 template< tag ... TL2>
1795 requires (
sizeof...(TL2) ==
sizeof...(TL))
1796 static std::size_t physical_size(
const range_class< TL2 ...>& rng)
1798 return (1 * ... * impl::physical_roundup<TL>(rng.template get<TL2>().size()));
1801 range_class< TL ...> rng_;
1802 impl::multiplier_list< TL ...> mult_;
1803 std::vector< E> arr_;
1808 template<
typename P,
typename C>
1811 template<
typename ... SL,
typename C>
1812 struct permute< tag_list< SL...>, C>
1814 using type =
typename C::template type< SL...>;
1817 template<
typename P,
typename C>
1818 using permute_t =
typename permute< P, C>::type;
1820 template<
typename E, tag ... TL>
1821 struct permutator_tensor_class
1823 template<
typename ... SL>
1824 using type = tensor_class< E, pick<selector<SL>, TL...> ...>;
1827 template< tag ... TL>
1828 struct permutator_range_class
1830 template<
typename ... SL>
1831 using type = range_class< pick<SL, TL...> ...>;
1834 struct permutator_range
1836 template<
typename ... SL>
1838 template< tag ... TL>
1839 static auto permute_range(
const range_class<TL...>& r)
1841 using range = range_class< pick<SL, TL...> ...>;
1842 return range((r.template get<SL>() & ...));
1856 template<
typename P,
typename E,
tag ... TL>
1860 template<
typename P,
tag ... TL>
1861 using permute_range_class = impl::permute_t< P, impl::permutator_range_class<TL...>>;
1863 template<
typename P,
tag ... TL>
1866 using permutator = impl::permute_t<P, impl::permutator_range>;
1867 return permutator::permute_range(r);
1875 template< selector_tag T>
1877 static constexpr bool is_tag =
true;
1878 static constexpr bool is_direct =
false;
1880 static constexpr bool is_selector =
true;
1881 using selector = c<T>;
1882 template<selector_tag T2>
1884 template<
typename RP2>
1885 using set_roundup = void;
1888 template< selector_tag T>
1893 template< selector_tag T>
1894 struct co_traits< c<T>> {
1911 using co = retag< typename impl::co_traits<selector<T>>
::co, T>;
1915 template<
typename X>
1916 struct co_list_traits;
1918 template<
tag ... TL>
1919 struct co_list_traits<
tag_list<TL ...>> {
1929 template<
typename X>
1930 using co_list =
typename impl::co_list_traits< X>::co_list;
1958 template<
typename E, tagged::tag STL0, tagged::tag DTL0>
1961 auto r0 = dvec.
range().template get<DTL0>();
1964 dvec[i0] = svec[i0];
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)
1971 auto r0 = dvec.
range().template get<DTL0>();
1974 auto sslice = svec[i0];
1975 auto dslice = dvec[i0];
1977 permute_tensor(sslice, dslice);
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)
1985 permute_tensor(svec.
view(), dvec.
view());
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