tuple.hpp Source File

tuple.hpp Source File#

Composable Kernel: tuple.hpp Source File
tile/core/container/tuple.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2018-2025, Advanced Micro Devices, Inc. All rights reserved.
3
4#pragma once
5
13#include <utility>
14#include <initializer_list>
15
16#ifndef CK_TILE_TUPLE_IMPL
17#define CK_TILE_TUPLE_IMPL 1
18#endif
19
20namespace ck_tile {
21
22namespace impl {
23template <typename T, index_t N>
24struct tuple_array_impl;
25}
26
27template <typename T, index_t N>
29
30namespace impl {
31
32// the place where content is stored
33template <index_t idx, typename T, bool is_empty = std::is_empty_v<T>>
35{
36};
37
38template <index_t idx, typename T>
39struct tuple_object<idx, T, true>
40{
42#if CK_TILE_TUPLE_IMPL == 0
43 template <typename U>
45 {
46 }
47 template <typename U>
49 {
50 }
51 template <typename U>
53 {
54 }
55#elif CK_TILE_TUPLE_IMPL == 1
56 template <typename U,
57 typename std::enable_if<!std::is_same<remove_cvref_t<U>, tuple_object>::value,
58 bool>::type = false>
60 {
61 }
62#endif
63};
64
65template <index_t idx, typename T>
66struct tuple_object<idx, T, false>
67{
69#if CK_TILE_TUPLE_IMPL == 0
70 template <typename U>
71 CK_TILE_HOST_DEVICE constexpr tuple_object(U&& e) : element(std::forward<U>(e))
72 {
73 }
74 template <typename U>
75 CK_TILE_HOST_DEVICE constexpr tuple_object(const U& e) : element(e)
76 {
77 }
78 template <typename U>
80 {
81 }
82#elif CK_TILE_TUPLE_IMPL == 1
83 template <typename U,
84 typename std::enable_if<!std::is_same<remove_cvref_t<U>, tuple_object>::value,
85 bool>::type = false>
86 CK_TILE_HOST_DEVICE constexpr tuple_object(U&& e) : element(std::forward<U>(e))
87 {
88 }
89#endif
91};
92
93// NOTE: we return a instance(not a reference) if content is empty
94template <index_t I, class T>
96{
97 return {};
98}
99
100template <index_t I, class T>
102{
103 return x.element;
104}
105
106template <index_t I, class T>
108{
109 return x.element;
110}
111
112template <index_t I, class T>
114{
115 return static_cast<T&&>(x.element);
116}
117
118template <typename index_seq, typename... T>
120
121template <index_t... I, typename... T>
122struct tuple_base<sequence<I...>, T...> : tuple_object<I, T>...
123{
124 CK_TILE_HOST_DEVICE constexpr tuple_base() = default;
125
126#if CK_TILE_TUPLE_CTOR_WITH_INITIALIZER_LIST
127#define _ILE() (std::initializer_list<U>{}.size() - 1)
128 template <typename U>
129 CK_TILE_HOST_DEVICE constexpr tuple_base(std::initializer_list<U> us)
130 : tuple_object<I, T>(static_cast<T>(*(us.begin() + (I >= _ILE() ? _ILE() : I))))...
131 {
132 }
133#undef _ILE
134#endif
135
136#if CK_TILE_TUPLE_IMPL == 0
137 template <class... U>
138 CK_TILE_HOST_DEVICE constexpr explicit tuple_base(U&&... u)
139 : tuple_object<I, T>(std::forward<U>(u))...
140 {
141 }
142
143 template <class... U>
144 CK_TILE_HOST_DEVICE constexpr explicit tuple_base(const U&... u) : tuple_object<I, T>(u)...
145 {
146 }
147
148 template <class... U>
149 CK_TILE_HOST_DEVICE constexpr explicit tuple_base(U&... u) : tuple_object<I, T>(u)...
150 {
151 }
152
153 template <class... U>
155 : tuple_object<I, T>(getv(static_cast<tuple_object<I, U>&&>(u)))...
156 {
157 }
158
159 template <class... U>
161 : tuple_object<I, T>(getv(static_cast<const tuple_object<I, U>&>(u)))...
162 {
163 }
164
165 template <class... U>
167 : tuple_object<I, T>(getv(static_cast<tuple_object<I, U>&>(u)))...
168 {
169 }
170#elif CK_TILE_TUPLE_IMPL == 1
171 template <class U,
172 typename std::enable_if<sizeof...(I) == 1 && sizeof...(T) == 1 &&
173 !std::is_same<remove_cvref_t<U>, tuple_base>::value,
174 bool>::type = false>
175 CK_TILE_HOST_DEVICE constexpr tuple_base(U&& u) : tuple_object<I, T>(std::forward<U>(u))...
176 {
177 }
178
179 template <typename... U, typename std::enable_if<sizeof...(U) >= 2, bool>::type = false>
180 CK_TILE_HOST_DEVICE constexpr tuple_base(U&&... u) : tuple_object<I, T>(std::forward<U>(u))...
181 {
182 static_assert(sizeof...(I) == sizeof...(T) && sizeof...(I) == sizeof...(U),
183 "wrong! inconsistent size");
184 }
185
186#endif
187};
188} // namespace impl
189
190template <class... T>
191struct tuple : impl::tuple_base<make_index_sequence<sizeof...(T)>, T...>
192{
194 static constexpr auto size() { return sizeof...(T); }
195 using base = impl::tuple_base<make_index_sequence<sizeof...(T)>, T...>;
196 CK_TILE_HOST_DEVICE constexpr tuple() = default;
197
198#if CK_TILE_TUPLE_CTOR_WITH_INITIALIZER_LIST
199 template <typename U>
200 CK_TILE_HOST_DEVICE constexpr tuple(std::initializer_list<U> us) : base(us)
201 {
202 }
203#endif
204
205#if CK_TILE_TUPLE_IMPL == 0
206 template <class... U>
207 CK_TILE_HOST_DEVICE constexpr tuple(U&&... u) : base(std::forward<U>(u)...)
208 {
209 }
210
211 template <class... U>
212 CK_TILE_HOST_DEVICE constexpr tuple(const U&... u) : base(u...)
213 {
214 }
215
216 template <class... U>
217 CK_TILE_HOST_DEVICE constexpr tuple(U&... u) : base(u...)
218 {
219 }
220
221 template <class... U>
223 : base(static_cast<impl::tuple_base<make_index_sequence<sizeof...(U)>, U...>&&>(u))
224 {
225 }
226
227 template <class... U>
229 : base(static_cast<const impl::tuple_base<make_index_sequence<sizeof...(U)>, U...>&>(u))
230 {
231 }
232
233 template <class... U>
235 : base(static_cast<impl::tuple_base<make_index_sequence<sizeof...(U)>, U...>&>(u))
236 {
237 }
238#elif CK_TILE_TUPLE_IMPL == 1
239 template <
240 typename U,
241 typename std::enable_if<sizeof...(T) == 1 && !std::is_same<remove_cvref_t<U>, tuple>::value,
242 bool>::type = false>
243 CK_TILE_HOST_DEVICE constexpr tuple(U&& u) : base(std::forward<U>(u))
244 {
245 }
246
247 template <typename... U,
248 typename std::enable_if<sizeof...(U) == sizeof...(T) && sizeof...(U) >= 2,
249 bool>::type = false>
250 CK_TILE_HOST_DEVICE constexpr tuple(U&&... u) : base(std::forward<U>(u)...)
251 {
252 }
253#endif
254 CK_TILE_HOST_DEVICE static constexpr bool is_static()
255 {
256 bool flag = true;
257
258 static_for<0, sizeof...(T), 1>{}([&flag](auto i) {
259 flag &= is_static_v<remove_cvref_t<__type_pack_element<i.value, T...>>>;
260 });
261
262 return flag;
263 }
264
265 CK_TILE_HOST_DEVICE static constexpr bool IsTuple() { return true; }
266
267#define TP_COM_() static_assert(I < size(), "wrong! out of range")
268 // clang-format off
269 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) get() const & { TP_COM_(); return impl::getv<I>(*this); }
270 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) get(number<I>) const & { TP_COM_(); return get<I>(); }
271 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) get() & { TP_COM_(); return impl::getv<I>(*this); }
272 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) get(number<I>) & { TP_COM_(); return get<I>(); }
273 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) get() && { TP_COM_(); return impl::getv<I>(std::move(*this)); }
274 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) get(number<I>) && { TP_COM_(); return std::move(*this).template get<I>(); }
275 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) get() const && { TP_COM_(); return impl::getv<I>(std::move(*this)); }
276 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) get(number<I>) const &&{ TP_COM_(); return std::move(*this).template get<I>(); }
277
278 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) at() const { TP_COM_(); return impl::getv<I>(*this); }
279 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) at(number<I>) const { TP_COM_(); return get<I>(); }
280 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) at() { TP_COM_(); return impl::getv<I>(*this); }
281 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) at(number<I>) { TP_COM_(); return get<I>(); }
282
283 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) operator[](number<I>) { TP_COM_(); return get<I>(); }
284 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) operator[](number<I>) const { TP_COM_(); return get<I>(); }
285 template<index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) operator()(number<I>) { TP_COM_(); return get<I>(); } // TODO: compatible
286
287 // below function should be used under tuple_array<> type, no extra check will perform here
288 template <typename Tx> CK_TILE_HOST_DEVICE constexpr decltype(auto) get_as() { return reinterpret_cast<tuple_array<Tx, size()>&>(*this); }
289 template <typename Tx> CK_TILE_HOST_DEVICE constexpr decltype(auto) get_as() const { return reinterpret_cast<const tuple_array<Tx, size()>&>(*this); }
290 // below index is for index *AFTER* type convert, not before
291 //template <typename Tx> CK_TILE_HOST_DEVICE constexpr decltype(auto) get_as(index_t i) { TP_COM_(); return reinterpret_cast<tuple_array<Tx, size()>&>(*this).at(i); }
292 //template <typename Tx> CK_TILE_HOST_DEVICE constexpr decltype(auto) get_as(index_t i) const { TP_COM_(); return reinterpret_cast<const tuple_array<Tx, size()>&>(*this).at(i); }
293 template <typename Tx, index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) get_as(number<I>) { TP_COM_(); return reinterpret_cast<tuple_array<Tx, size()>&>(*this).at(number<I>{}); }
294 template <typename Tx, index_t I> CK_TILE_HOST_DEVICE constexpr decltype(auto) get_as(number<I>) const { TP_COM_(); return reinterpret_cast<const tuple_array<Tx, size()>&>(*this).at(number<I>{}); }
295
296 // template <typename Tx> CK_TILE_HOST_DEVICE constexpr void set_as(index_t i, const Tx & x) { TP_COM_(); reinterpret_cast<tuple_array<Tx, size()>&>(*this).at(i) = x; }
297 template <typename Tx, index_t I> CK_TILE_HOST_DEVICE constexpr void set_as(number<I>, const Tx & x) { TP_COM_(); reinterpret_cast<tuple_array<Tx, size()>&>(*this).at(number<I>{}) = x; }
298
299 // clang-format on
300#undef TP_COM_
301};
302
303template <typename... T>
305{
306 printf("tuple<");
307 if constexpr(sizeof...(T) > 0)
308 {
309 bool first = true;
310 static_for<0, sizeof...(T), 1>{}([&t, &first](auto i) {
311 if(!first)
312 printf(", ");
313 print(t.get(i));
314 first = false;
315 });
316 }
317 printf(">");
318}
319
320template <typename, typename>
321struct vector_traits;
322
323// specialization for array
324template <typename... T>
325struct vector_traits<tuple<T...>, void>
326{
327 using scalar_type = __type_pack_element<0, T...>;
328 static constexpr index_t vector_size = sizeof...(T);
329};
330
331// template <class... T>
332// CK_TILE_HOST_DEVICE constexpr
333// tuple<T...>
334// make_tuple(T const&... t)
335// {
336// return {t...};
337// }
338template <typename... Xs>
340{
341 bool same = true;
342
343 static_for<0, sizeof...(Xs), 1>{}([&](auto i) {
344 if(a[i] != b[i])
345 {
346 same = false;
347 }
348 });
349
350 return same;
351}
352
353template <typename... Xs>
355{
356 return !(a == b);
357}
358
359template <typename... Xs>
360CK_TILE_HOST_DEVICE constexpr auto make_tuple(Xs&&... xs)
361{
362 // here xs is always a lvalue as function arg
363 // Xs may deduced as (e.g try to pass in a integer in following cases)
364 // 1). if pass in a rvalue (like function return or int{}) -> Xs is "int"
365 // 2). if pass in a const lvalue -> Xs is "const int &"
366 // 3). if pass in a non-const lvalue -> Xs is "int &"
367 // so the return type of std::forward will dependes on Xs
368 // 1). std::forward -> int&&
369 // 2). std::forward -> const int&
370 // 3). std::forward -> int&
371 return tuple<remove_cvref_t<Xs>...>(std::forward<Xs>(xs)...);
372}
373
374// https://en.cppreference.com/w/cpp/utility/tuple/tie
375template <typename... Args>
376constexpr tuple<Args&...> tie(Args&... args) noexcept
377{
378 return {args...};
379}
380
381template <typename X, typename Y>
383
384template <typename... Xs, typename... Ys>
385struct tuple_concat<tuple<Xs...>, tuple<Ys...>>
386{
387 using type = tuple<Xs..., Ys...>;
388};
389
390namespace impl {
391// be very careful using this type (because we want the internal type)
392// template deduction will fail if infering the inner type
393// e.g.
394// template<typename T, index_t N> using some_wrapper = typename tuple_array_impl<T, N>::type;
395// template<typename T, index_t N> void foo(const some_wrapper<T, N>&) {}
396// -> compiler will fail to deduce this type, because this is under non-deduced context
397// (https://en.cppreference.com/w/cpp/language/template_argument_deduction, "Non-deduced
398// contexts")
399//
400// -> use this instead
401// template<typename Tup> void foo(const Tup&) {}
402template <typename T, index_t N>
404{
405 using type = typename tuple_concat<typename tuple_array_impl<T, N / 2>::type,
406 typename tuple_array_impl<T, N - N / 2>::type>::type;
407};
408
409template <typename T>
411{
412 using type = tuple<>;
413};
414
415template <typename T>
417{
418 using type = tuple<T>;
419};
420} // namespace impl
421
422template <typename F, index_t... ids>
424{
425 return make_tuple(f(number<ids>{})...);
426}
427
428template <typename F, index_t N>
433
434template <typename F, index_t N>
436{
437 return unpack([&f](auto&&... is) { return tie(f(is)...); },
439}
440
441// tx and ty are tuple of references, return type of will tuple of referennce (not rvalue)
442template <typename... X, typename... Y>
444 const tuple<Y&...>& ty)
445{
446 return unpack2(
447 [&](auto&&... zs) { return tuple<decltype(zs)...>{std::forward<decltype(zs)>(zs)...}; },
448 tx,
449 ty);
450}
451
452template <typename... X, typename... Y>
453CK_TILE_HOST_DEVICE constexpr auto concat_tuple(const tuple<X...>& tx, const tuple<Y...>& ty)
454{
455 return unpack2(
456 [&](auto... zs) { return tuple<decltype(zs)...>{std::forward<decltype(zs)>(zs)...}; },
457 tx,
458 ty);
459}
460
461// Support any number of tuples to concat (also 1)
462template <typename... X>
464{
465 return tx;
466}
467
468template <typename... X, typename... Tuples>
469CK_TILE_HOST_DEVICE constexpr auto concat_tuple(const tuple<X...>& tx, const Tuples&... tuples)
470{
471 return concat_tuple(tx, concat_tuple(tuples...));
472}
473
474namespace detail {
475
476template <typename F, typename X, index_t... Is>
478{
479 return make_tuple(f(x.at(number<Is>{}))...);
480}
481
482template <typename F, typename X, typename Y, index_t... Is>
483CK_TILE_HOST_DEVICE constexpr auto
484transform_tuples_impl(F f, const X& x, const Y& y, sequence<Is...>)
485{
486 return make_tuple(f(x.at(number<Is>{}), y.at(number<Is>{}))...);
487}
488
489template <typename F, typename X, typename Y, typename Z, index_t... Is>
490CK_TILE_HOST_DEVICE constexpr auto
491transform_tuples_impl(F f, const X& x, const Y& y, const Z& z, sequence<Is...>)
492{
493 return make_tuple(f(x.at(number<Is>{}), y.at(number<Is>{}), z.at(number<Is>{}))...);
494}
495
496template <typename F, typename Tuple, index_t... Is>
497constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, sequence<Is...>)
498{
499 return std::forward<F>(f)(std::forward<Tuple>(t).get(number<Is>{})...);
500}
501
502} // namespace detail
503
504template <typename F, typename X>
505CK_TILE_HOST_DEVICE constexpr auto transform_tuples(F f, const X& x)
506{
508 f, x, typename arithmetic_sequence_gen<0, X::size(), 1>::type{});
509}
510
511template <typename F, typename X, typename Y>
512CK_TILE_HOST_DEVICE constexpr auto transform_tuples(F f, const X& x, const Y& y)
513{
515 f, x, y, typename arithmetic_sequence_gen<0, X::size(), 1>::type{});
516}
517
518template <typename F, typename X, typename Y, typename Z>
519CK_TILE_HOST_DEVICE constexpr auto transform_tuples(F f, const X& x, const Y& y, const Z& z)
520{
522 f, x, y, z, typename arithmetic_sequence_gen<0, X::size(), 1>::type{});
523}
524
525template <typename F, typename Tuple>
526constexpr decltype(auto) apply(F&& f, Tuple&& t)
527{
528 constexpr index_t N = std::decay_t<Tuple>::size();
529 return detail::apply_impl(std::forward<F>(f), std::forward<Tuple>(t), make_index_sequence<N>{});
530}
531
532namespace detail {
533
534template <typename F, typename X, index_t... Is>
536{
537 return concat_tuple(f(x.at(number<Is>{}))...);
538}
539
540} // namespace detail
541
542// make sure F return at least a tuple
543// e.g. x : tuple<X, Y>, f will return tuple<Z, W>
544// this function will return
545template <typename F, typename X>
546CK_TILE_HOST_DEVICE constexpr auto embed_tuples(F f, const X& x)
547{
549 f, x, typename arithmetic_sequence_gen<0, X::size(), 1>::type{});
550}
551
552// By default unroll to the flatten
553template <index_t Depth = 0, index_t MaxDepth = -1>
555{
556 return t;
557}
558
559template <index_t Depth = 0, index_t MaxDepth = -1, typename T>
560CK_TILE_HOST_DEVICE constexpr auto unroll_nested_tuple(const T& t)
561{
562 return make_tuple(t);
563}
564
565template <index_t Depth = 0, index_t MaxDepth = -1, typename... Ts>
567{
568 if constexpr(Depth == MaxDepth)
569 {
570 return t;
571 }
572 else
573 {
574 return unpack(
575 [&](auto&&... ts) {
577 },
578 t);
579 }
580}
581
582template <typename... Ts>
584{
585 return generate_tuple(
586 [&](auto i) {
587 using Idx = number<tuple<Ts...>::size() - i - 1>;
588 return t.at(Idx{});
589 },
591}
592
593// Reduce tuple values in specific range using Function
594template <index_t Idx, index_t End, typename F, typename... Ts>
595CK_TILE_HOST_DEVICE constexpr auto tuple_reduce(F&& f, const tuple<Ts...>& t)
596{
597 static_assert(Idx < End, "Wrong parameters for tuple_reduce");
598 if constexpr(Idx + 1 == End)
599 {
600 return t.at(number<Idx>{});
601 }
602 else
603 {
604 return f(t.at(number<Idx>{}), tuple_reduce<Idx + 1, End>(f, t));
605 }
606}
607
608template <typename T>
609using is_tuple = decltype(std::declval<T&>().IsTuple());
610
611template <typename... Ts>
613{
614 return (is_detected<is_tuple, Ts>::value || ...);
615}
616
617template <index_t depth = 0, typename T>
618CK_TILE_HOST_DEVICE constexpr auto tuple_depth(const T&)
619{
620 return depth;
621}
622
623template <index_t depth = 0, typename... Ts>
625{
626 return max(tuple_depth<depth + 1>(Ts{})...);
627}
628
629template <typename... Seqs>
631{
632 constexpr index_t n0 = sizeof...(Seqs);
633
634 constexpr index_t max_n1 = [&] {
635 index_t max_n1_ = 0;
636
637 static_for<0, n0, 1>{}([&](auto i0) {
638 constexpr index_t n1 = t_of_s[i0].size();
639
640 max_n1_ = max_n1_ < n1 ? n1 : max_n1_;
641 });
642
643 return max_n1_;
644 }();
645
646 array<array<index_t, max_n1>, n0> a_of_a{{-1}};
647
648 static_for<0, n0, 1>{}([&](auto i0) {
649 constexpr index_t n1 = t_of_s[i0].size();
650
651 static_for<0, n1, 1>{}([&](auto i1) { a_of_a(i0)(i1) = t_of_s[i0][i1]; });
652 });
653
654 return a_of_a;
655}
656
657// Here should use MultiIndex<NSize>, instead of tuple<Ys...>, although the former
658// is the alias of the latter. This is because compiler cannot infer the NSize if
659// using MultiIndex<NSize>
660// TODO: how to fix this?
661template <typename... Ys,
662 typename X,
663 std::enable_if_t<!std::is_integral<X>::value && !std::is_floating_point<X>::value, bool> =
664 false>
665CK_TILE_HOST_DEVICE constexpr auto operator+=(tuple<Ys...>& y, const X& x)
666{
667 static_assert(X::size() == sizeof...(Ys), "wrong! size not the same");
668 constexpr index_t NSize = sizeof...(Ys);
669 static_for<0, NSize, 1>{}([&](auto i) { y[i] += x[i]; });
670 return y;
671}
672
673template <typename... Ys,
674 typename X,
675 std::enable_if_t<!std::is_integral<X>::value && !std::is_floating_point<X>::value, bool> =
676 false>
677CK_TILE_HOST_DEVICE constexpr auto operator-=(tuple<Ys...>& y, const X& x)
678{
679 static_assert(X::size() == sizeof...(Ys), "wrong! size not the same");
680 constexpr index_t NSize = sizeof...(Ys);
681 static_for<0, NSize, 1>{}([&](auto i) { y[i] -= x[i]; });
682 return y;
683}
684
685template <typename... Xs,
686 typename Y,
687 std::enable_if_t<!std::is_integral<Y>::value && !std::is_floating_point<Y>::value, bool> =
688 false>
689CK_TILE_HOST_DEVICE constexpr auto operator+(const tuple<Xs...>& x, const Y& y)
690{
691 static_assert(Y::size() == sizeof...(Xs), "wrong! size not the same");
692 constexpr index_t NSize = sizeof...(Xs);
693
694 tuple<Xs...> r;
695 static_for<0, NSize, 1>{}([&](auto i) { r[i] = x[i] + y[i]; });
696 return r;
697}
698
699template <typename... Xs, typename... Ys>
700CK_TILE_HOST_DEVICE constexpr auto operator+(const tuple<Xs...>& x, const tuple<Ys...>& y)
701{
702 static_assert(sizeof...(Xs) == sizeof...(Ys), "wrong!");
703 constexpr index_t NSize = sizeof...(Xs);
704 return generate_tuple([&](auto i) { return x[i] + y[i]; }, number<NSize>{});
705}
706
707template <typename... Xs,
708 typename Y,
709 std::enable_if_t<!std::is_integral<Y>::value && !std::is_floating_point<Y>::value, bool> =
710 false>
711CK_TILE_HOST_DEVICE constexpr auto operator-(const tuple<Xs...>& x, const Y& y)
712{
713 static_assert(Y::size() == sizeof...(Xs), "wrong! size not the same");
714 constexpr index_t NSize = sizeof...(Xs);
715
716 tuple<Xs...> r;
717 static_for<0, NSize, 1>{}([&](auto i) { r[i] = x[i] - y[i]; });
718 return r;
719}
720
721template <typename... Xs, typename... Ys>
722CK_TILE_HOST_DEVICE constexpr auto operator-(const tuple<Xs...>& x, const tuple<Ys...>& y)
723{
724 static_assert(sizeof...(Xs) == sizeof...(Ys), "wrong!");
725 constexpr index_t NSize = sizeof...(Xs);
726 return generate_tuple([&](auto i) { return x[i] - y[i]; }, number<NSize>{});
727}
728
729template <typename... Xs,
730 typename Y,
731 std::enable_if_t<!std::is_integral<Y>::value && !std::is_floating_point<Y>::value, bool> =
732 false>
733CK_TILE_HOST_DEVICE constexpr auto operator*(const tuple<Xs...>& x, const Y& y)
734{
735 static_assert(Y::size() == sizeof...(Xs), "wrong! size not the same");
736 constexpr index_t NSize = sizeof...(Xs);
737
738 tuple<Xs...> r;
739 static_for<0, NSize, 1>{}([&](auto i) { r[i] = x[i] * y[i]; });
740 return r;
741}
742
743// MultiIndex = scalar * MultiIndex
744template <
745 typename... Xs,
746 typename Y,
747 std::enable_if_t<std::is_integral<Y>::value || std::is_floating_point<Y>::value, bool> = false>
748CK_TILE_HOST_DEVICE constexpr auto operator*(Y a, const tuple<Xs...>& x)
749{
750 constexpr index_t NSize = sizeof...(Xs);
751 tuple<Xs...> r;
752 static_for<0, NSize, 1>{}([&](auto i) { r[i] = a * x[i]; });
753 return r;
754}
755
756// MultiIndex = MultiIndex * scalar
757template <
758 typename... Xs,
759 typename Y,
760 std::enable_if_t<std::is_integral<Y>::value || std::is_floating_point<Y>::value, bool> = false>
761CK_TILE_HOST_DEVICE constexpr auto operator*(const tuple<Xs...>& x, Y a)
762{
763 return a * x;
764}
765
766template <typename... Xs, typename... Ys>
767CK_TILE_HOST_DEVICE constexpr auto operator*(const tuple<Xs...>& x, const tuple<Ys...>& y)
768{
769 static_assert(sizeof...(Xs) == sizeof...(Ys), "wrong!");
770 constexpr index_t NSize = sizeof...(Xs);
771 return generate_tuple([&](auto i) { return x[i] * y[i]; }, number<NSize>{});
772}
773
774template <typename... Xs, typename... Ys>
775CK_TILE_HOST_DEVICE constexpr auto operator/(const tuple<Xs...>& x, const tuple<Ys...>& y)
776{
777 static_assert(sizeof...(Xs) == sizeof...(Ys), "wrong!");
778 constexpr index_t NSize = sizeof...(Xs);
779 return generate_tuple([&](auto i) { return x[i] / y[i]; }, number<NSize>{});
780}
781
782} // namespace ck_tile
783
784#include <tuple>
785// WARNING: needed by compiler for C++ structured binding support only, don't use this
786namespace std {
787
788template <typename... Ts>
789struct tuple_size<ck_tile::tuple<Ts...>> : std::integral_constant<std::size_t, sizeof...(Ts)>
790{
791};
792
793template <std::size_t I, typename... Ts>
794struct tuple_element<I, ck_tile::tuple<Ts...>> : std::tuple_element<I, std::tuple<Ts...>>
795{
796};
797
798template <typename... Ts>
799struct tuple_size<const ck_tile::tuple<Ts...>> : std::integral_constant<std::size_t, sizeof...(Ts)>
800{
801};
802
803template <std::size_t I, typename... Ts>
804struct tuple_element<I, const ck_tile::tuple<Ts...>>
805 : std::tuple_element<I, const std::tuple<Ts...>>
806{
807};
808
809} // namespace std
810
811#if 1
812#define TO_TUPLE_OF_NUMBER(a, n) \
813 _Pragma("clang diagnostic push") _Pragma( \
814 "clang diagnostic ignored \"-Wc++20-extensions\"")[a]<ck_tile::index_t... IDX_IDX_>( \
815 ck_tile::sequence<IDX_IDX_...>) \
816 { \
817 return ck_tile::tuple<ck_tile::number<a[ck_tile::number<IDX_IDX_>{}]>...>{}; \
818 } \
819 (ck_tile::make_index_sequence<n>{}) _Pragma("clang diagnostic pop")
820#else
821#define TO_TUPLE_OF_NUMBER(arr, n_) \
822 [&arr, n_] { \
823 static_assert(arr.size() >= n_, "wrong! out of bound"); \
824 \
825 static_assert(n_ < 7, "not implemented"); \
826 \
827 if constexpr(n_ == 0) \
828 { \
829 return ck_tile::tuple<>{}; \
830 } \
831 else if constexpr(n_ == 1) \
832 { \
833 return ck_tile::tuple<number<arr[0]>>{}; \
834 } \
835 else if constexpr(n_ == 2) \
836 { \
837 return ck_tile::tuple<number<arr[0]>, number<arr[1]>>{}; \
838 } \
839 else if constexpr(n_ == 3) \
840 { \
841 return ck_tile::tuple<number<arr[0]>, number<arr[1]>, number<arr[2]>>{}; \
842 } \
843 else if constexpr(n_ == 4) \
844 { \
845 return ck_tile:: \
846 tuple<number<arr[0]>, number<arr[1]>, number<arr[2]>, number<arr[3]>>{}; \
847 } \
848 else if constexpr(n_ == 5) \
849 { \
850 return ck_tile::tuple<number<arr[0]>, \
851 number<arr[1]>, \
852 number<arr[2]>, \
853 number<arr[3]>, \
854 number<arr[4]>>{}; \
855 } \
856 else if constexpr(n_ == 6) \
857 { \
858 return ck_tile::tuple<number<arr[0]>, \
859 number<arr[1]>, \
860 number<arr[2]>, \
861 number<arr[3]>, \
862 number<arr[4]>, \
863 number<arr[5]>>{}; \
864 } \
865 }()
866#endif
#define CK_TILE_HOST_DEVICE
Definition config.hpp:42
__host__ __device__ constexpr auto depth(const Layout< Shape, UnrolledDescriptorType > &layout)
Get depth of the layout shape (return 0 if scalar).
Definition layout_utils.hpp:371
constexpr decltype(auto) apply_impl(F &&f, Tuple &&t, sequence< Is... >)
Definition tile/core/container/tuple.hpp:497
CK_TILE_HOST_DEVICE constexpr auto transform_tuples_impl(F f, const X &x, sequence< Is... >)
Definition tile/core/container/tuple.hpp:477
CK_TILE_HOST_DEVICE constexpr auto embed_tuples_impl(F f, const X &x, sequence< Is... >)
Definition tile/core/container/tuple.hpp:535
Definition tile/core/arch/amd_buffer_addressing.hpp:110
CK_TILE_HOST_DEVICE constexpr T getv(const tuple_object< I, T, true > &)
Definition tile/core/container/tuple.hpp:95
Definition tile/core/algorithm/cluster_descriptor.hpp:13
constexpr decltype(auto) apply(F &&f, Tuple &&t)
Definition tile/core/container/tuple.hpp:526
CK_TILE_HOST_DEVICE constexpr auto unpack2(F &&f, X &&x, Y &&y)
Definition tile/core/utility/functional.hpp:209
remove_cv_t< std::remove_reference_t< T > > remove_cvref_t
Definition type_traits.hpp:21
CK_TILE_HOST_DEVICE constexpr auto generate_tuple_for(F &&f, sequence< ids... >)
Definition tile/core/container/tuple.hpp:423
constexpr tuple< Args &... > tie(Args &... args) noexcept
Definition tile/core/container/tuple.hpp:376
CK_TILE_HOST_DEVICE constexpr auto operator-=(multi_index< NSize > &y, const X &x)
Definition tile/core/container/multi_index.hpp:47
CK_TILE_HOST_DEVICE constexpr auto operator*(const multi_index< NSize > &a, const T &b)
Definition tile/core/container/multi_index.hpp:75
CK_TILE_HOST_DEVICE constexpr auto tuple_reverse(const tuple< Ts... > &t)
Definition tile/core/container/tuple.hpp:583
typename detail::detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition type_traits.hpp:67
CK_TILE_HOST_DEVICE constexpr auto concat_tuple_of_reference(const tuple< X &... > &tx, const tuple< Y &... > &ty)
Definition tile/core/container/tuple.hpp:443
CK_TILE_HOST_DEVICE constexpr auto operator+(const multi_index< NSize > &a, const T &b)
Definition tile/core/container/multi_index.hpp:55
typename __make_integer_seq< impl::__integer_sequence, index_t, N >::seq_type make_index_sequence
Definition tile/core/container/sequence.hpp:230
CK_TILE_HOST_DEVICE constexpr auto operator-(const multi_index< NSize > &a, const T &b)
Definition tile/core/container/multi_index.hpp:65
CK_TILE_HOST_DEVICE constexpr auto is_nested_tuple(const tuple< Ts... > &)
Definition tile/core/container/tuple.hpp:612
CK_TILE_HOST_DEVICE constexpr auto transform_tuples(F f, const X &x)
Definition tile/core/container/tuple.hpp:505
constant< v > number
Definition tile/core/numeric/integral_constant.hpp:37
CK_TILE_HOST_DEVICE constexpr auto tuple_depth(const T &)
Definition tile/core/container/tuple.hpp:618
CK_TILE_HOST_DEVICE constexpr auto generate_tuple(F &&f, number< N >)
Definition tile/core/container/tuple.hpp:429
CK_TILE_HOST_DEVICE constexpr auto generate_tie(F &&f, number< N >)
Definition tile/core/container/tuple.hpp:435
constexpr bool is_static_v
Definition type_traits.hpp:90
CK_TILE_HOST_DEVICE constexpr auto unpack(F &&f, X &&x)
Definition tile/core/utility/functional.hpp:200
CK_TILE_HOST_DEVICE constexpr auto operator/(sequence< Xs... >, sequence< Ys... >)
Definition tile/core/container/sequence.hpp:737
CK_TILE_HOST_DEVICE constexpr T max(T x)
Definition tile/core/numeric/math.hpp:161
CK_TILE_HOST_DEVICE constexpr auto concat_tuple(const tuple< X... > &tx, const tuple< Y... > &ty)
Definition tile/core/container/tuple.hpp:453
CK_TILE_HOST_DEVICE constexpr auto unroll_nested_tuple(const tuple<> &t)
Definition tile/core/container/tuple.hpp:554
int32_t index_t
Definition integer.hpp:9
CK_TILE_HOST_DEVICE constexpr bool operator==(const array< T, Size > &a, const array< T, Size > &b)
Definition tile/core/container/array.hpp:263
CK_TILE_HOST_DEVICE constexpr auto embed_tuples(F f, const X &x)
Definition tile/core/container/tuple.hpp:546
CK_TILE_HOST_DEVICE constexpr auto to_array_of_array(tuple< Seqs... > t_of_s)
Definition tile/core/container/tuple.hpp:630
typename impl::tuple_array_impl< T, N >::type tuple_array
Definition tile/core/container/tuple.hpp:28
decltype(std::declval< T & >().IsTuple()) is_tuple
Definition tile/core/container/tuple.hpp:609
CK_TILE_HOST_DEVICE constexpr auto tuple_reduce(F &&f, const tuple< Ts... > &t)
Definition tile/core/container/tuple.hpp:595
CK_TILE_HOST_DEVICE constexpr auto operator+=(multi_index< NSize > &y, const X &x)
Definition tile/core/container/multi_index.hpp:39
CK_TILE_HOST_DEVICE constexpr auto make_tuple(Xs &&... xs)
Definition tile/core/container/tuple.hpp:360
CK_TILE_HOST_DEVICE constexpr bool operator!=(const array< T, Size > &a, const array< T, Size > &b)
Definition tile/core/container/array.hpp:280
STL namespace.
const GenericPointer< typename T::ValueType > T2 value
Definition pointer.h:1697
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1517
Definition tile/core/container/sequence.hpp:287
typename std::conditional< kHasContent, type0, type1 >::type type
Definition tile/core/container/sequence.hpp:302
A fixed-size array container similar to std::array with additional utilities.
Definition tile/core/container/array.hpp:43
tuple<> type
Definition tile/core/container/tuple.hpp:412
tuple< T > type
Definition tile/core/container/tuple.hpp:418
Definition tile/core/container/tuple.hpp:404
typename tuple_concat< typename tuple_array_impl< T, N/2 >::type, typename tuple_array_impl< T, N - N/2 >::type >::type type
Definition tile/core/container/tuple.hpp:405
CK_TILE_HOST_DEVICE constexpr tuple_base(U &... u)
Definition tile/core/container/tuple.hpp:149
CK_TILE_HOST_DEVICE constexpr tuple_base(tuple_base< sequence< I... >, U... > &&u)
Definition tile/core/container/tuple.hpp:154
CK_TILE_HOST_DEVICE constexpr tuple_base(tuple_base< sequence< I... >, U... > &u)
Definition tile/core/container/tuple.hpp:166
CK_TILE_HOST_DEVICE constexpr tuple_base(const U &... u)
Definition tile/core/container/tuple.hpp:144
CK_TILE_HOST_DEVICE constexpr tuple_base(const tuple_base< sequence< I... >, U... > &u)
Definition tile/core/container/tuple.hpp:160
CK_TILE_HOST_DEVICE constexpr tuple_base()=default
CK_TILE_HOST_DEVICE constexpr tuple_base(U &&... u)
Definition tile/core/container/tuple.hpp:138
Definition tile/core/container/tuple.hpp:119
CK_TILE_HOST_DEVICE constexpr tuple_object()
Definition tile/core/container/tuple.hpp:68
CK_TILE_HOST_DEVICE constexpr tuple_object(U &&e)
Definition tile/core/container/tuple.hpp:71
T element
Definition tile/core/container/tuple.hpp:90
CK_TILE_HOST_DEVICE constexpr tuple_object(const U &e)
Definition tile/core/container/tuple.hpp:75
CK_TILE_HOST_DEVICE constexpr tuple_object(U &e)
Definition tile/core/container/tuple.hpp:79
CK_TILE_HOST_DEVICE constexpr tuple_object(U &&)
Definition tile/core/container/tuple.hpp:44
CK_TILE_HOST_DEVICE constexpr tuple_object(const U &)
Definition tile/core/container/tuple.hpp:48
CK_TILE_HOST_DEVICE constexpr tuple_object()
Definition tile/core/container/tuple.hpp:41
CK_TILE_HOST_DEVICE constexpr tuple_object(U &)
Definition tile/core/container/tuple.hpp:52
Definition tile/core/container/tuple.hpp:35
Definition tile/core/container/sequence.hpp:49
Definition tile/core/utility/functional.hpp:43
tuple< Xs..., Ys... > type
Definition tile/core/container/tuple.hpp:387
Definition tile/core/container/tuple.hpp:382
Definition tile/core/container/tuple.hpp:192
CK_TILE_HOST_DEVICE constexpr tuple(U &&... u)
Definition tile/core/container/tuple.hpp:207
static CK_TILE_HOST_DEVICE constexpr bool IsTuple()
Definition tile/core/container/tuple.hpp:265
CK_TILE_HOST_DEVICE constexpr decltype(auto) get() &
Definition tile/core/container/tuple.hpp:271
impl::tuple_base< make_index_sequence< sizeof...(T)>, T... > base
Definition tile/core/container/tuple.hpp:195
CK_TILE_HOST_DEVICE constexpr tuple()=default
CK_TILE_HOST_DEVICE constexpr decltype(auto) get_as() const
Definition tile/core/container/tuple.hpp:289
CK_TILE_HOST_DEVICE constexpr decltype(auto) at(number< I >)
Definition tile/core/container/tuple.hpp:281
CK_TILE_HOST_DEVICE constexpr tuple(tuple< U... > &u)
Definition tile/core/container/tuple.hpp:234
CK_TILE_HOST_DEVICE constexpr tuple(U &... u)
Definition tile/core/container/tuple.hpp:217
static CK_TILE_HOST_DEVICE constexpr bool is_static()
Definition tile/core/container/tuple.hpp:254
CK_TILE_HOST_DEVICE constexpr decltype(auto) at(number< I >) const
Definition tile/core/container/tuple.hpp:279
static CK_TILE_HOST_DEVICE constexpr auto size()
Definition tile/core/container/tuple.hpp:194
CK_TILE_HOST_DEVICE constexpr tuple(const U &... u)
Definition tile/core/container/tuple.hpp:212
CK_TILE_HOST_DEVICE constexpr tuple(const tuple< U... > &u)
Definition tile/core/container/tuple.hpp:228
CK_TILE_HOST_DEVICE constexpr decltype(auto) get_as(number< I >) const
Definition tile/core/container/tuple.hpp:294
CK_TILE_HOST_DEVICE constexpr decltype(auto) get(number< I >) &
Definition tile/core/container/tuple.hpp:272
CK_TILE_HOST_DEVICE constexpr decltype(auto) at() const
Definition tile/core/container/tuple.hpp:278
CK_TILE_HOST_DEVICE constexpr decltype(auto) get(number< I >) const &&
Definition tile/core/container/tuple.hpp:276
CK_TILE_HOST_DEVICE constexpr tuple(tuple< U... > &&u)
Definition tile/core/container/tuple.hpp:222
CK_TILE_HOST_DEVICE constexpr decltype(auto) get_as()
Definition tile/core/container/tuple.hpp:288
CK_TILE_HOST_DEVICE constexpr decltype(auto) get() const &&
Definition tile/core/container/tuple.hpp:275
CK_TILE_HOST_DEVICE constexpr decltype(auto) get(number< I >) const &
Definition tile/core/container/tuple.hpp:270
CK_TILE_HOST_DEVICE constexpr decltype(auto) get_as(number< I >)
Definition tile/core/container/tuple.hpp:293
CK_TILE_HOST_DEVICE constexpr decltype(auto) get() const &
Definition tile/core/container/tuple.hpp:269
CK_TILE_HOST_DEVICE constexpr decltype(auto) at()
Definition tile/core/container/tuple.hpp:280
CK_TILE_HOST_DEVICE constexpr decltype(auto) get() &&
Definition tile/core/container/tuple.hpp:273
CK_TILE_HOST_DEVICE constexpr decltype(auto) get(number< I >) &&
Definition tile/core/container/tuple.hpp:274
CK_TILE_HOST_DEVICE constexpr void set_as(number< I >, const Tx &x)
Definition tile/core/container/tuple.hpp:297
static constexpr index_t vector_size
Definition tile/core/container/tuple.hpp:328
__type_pack_element< 0, T... > scalar_type
Definition tile/core/container/tuple.hpp:327
Definition vector_type.hpp:90
#define TP_COM_()
Definition tile/core/container/tuple.hpp:267