4#include <AMReX_Config.H>
17 template <
class... Ts>
18 using Tuple = std::tuple<Ts...>;
26template <std::
size_t I,
typename T>
27struct gpu_tuple_element
30 constexpr gpu_tuple_element ()
requires (std::is_default_constructible_v<T>) {}
32 explicit constexpr gpu_tuple_element (T
const& a_value)
37 requires (std::is_convertible_v<U&&,T>)
38 explicit constexpr gpu_tuple_element (U && a_value)
39 : m_value(std::forward<U>(a_value))
45template <std::size_t I,
typename... Ts>
struct gpu_tuple_impl;
47template <std::size_t I,
typename Head,
typename... Tail>
48struct gpu_tuple_impl<I, Head, Tail...>
49 :
public gpu_tuple_impl<I+1, Tail...>,
50 public gpu_tuple_element<I, Head>
53 constexpr gpu_tuple_impl ()
requires (std::is_default_constructible_v<Head>) {}
55 constexpr gpu_tuple_impl (Head
const& a_head, Tail
const&... a_tail)
56 : gpu_tuple_impl<I+1, Tail...>(a_tail...),
57 gpu_tuple_element<I, Head>(a_head)
60 template <
typename UH,
typename... UT>
61 requires (std::is_convertible_v<UH&&,Head>)
62 constexpr gpu_tuple_impl (UH&& a_head, UT &&... a_tail)
63 : gpu_tuple_impl<I+1, Tail...>(std::forward<UT>(a_tail)...),
64 gpu_tuple_element<I, Head>(std::forward<UH>(a_head))
68template <std::
size_t I,
typename Head>
69struct gpu_tuple_impl<I, Head>
70 :
public gpu_tuple_element<I, Head>
74 constexpr gpu_tuple_impl ()
requires (std::is_default_constructible_v<Head>) {}
76 explicit constexpr gpu_tuple_impl (Head
const& a_head)
77 : gpu_tuple_element<I, Head>(a_head)
81 requires (std::is_convertible_v<U&&,Head>)
82 explicit constexpr gpu_tuple_impl (U&& a_head)
83 : gpu_tuple_element<I, Head>(std::forward<U>(a_head))
95template <
typename... Ts>
97 :
public detail::gpu_tuple_impl<0, Ts...>
104 : detail::gpu_tuple_impl<0, Ts...>(args...)
107 template <
typename... Us>
108 requires (
sizeof...(Us) ==
sizeof...(Ts))
110 : detail::gpu_tuple_impl<0, Ts...>(std::forward<Us>(args)...)
113 template <
typename... Us>
119 template <
typename... Us>
129template <
typename... Ts>
131 :
public std::integral_constant<std::size_t, sizeof...(Ts)> {};
137template <std::size_t I,
typename Head,
typename... Tail>
141template <
typename Head,
typename... Tail>
151template <std::size_t I,
typename... Ts>
155get_impl (detail::gpu_tuple_element
161template <std::size_t I,
typename... Ts>
164typename GpuTupleElement<I, GpuTuple<Ts...> >::type
const&
165get_impl (detail::gpu_tuple_element
166 <I,
typename GpuTupleElement<I, GpuTuple<Ts...> >::type>
const& te)
noexcept
171template <std::size_t I,
typename... Ts>
174typename GpuTupleElement<I, GpuTuple<Ts...> >::type &&
175get_impl (detail::gpu_tuple_element
176 <I,
typename GpuTupleElement<I, GpuTuple<Ts...> >::type> && te)
noexcept
178 return std::move(te).m_value;
184template <std::size_t I,
typename... Ts>
187typename GpuTupleElement<I, GpuTuple<Ts...> >::type&
190 return detail::get_impl<I,Ts...>(tup);
193template <std::size_t I,
typename... Ts>
196typename GpuTupleElement<I, GpuTuple<Ts...> >::type
const&
199 return detail::get_impl<I,Ts...>(tup);
202template <std::size_t I,
typename... Ts>
205typename GpuTupleElement<I, GpuTuple<Ts...> >::type &&
208 return detail::get_impl<I,Ts...>(std::move(tup));
213 template <std::
size_t I, std::
size_t N,
typename TP1,
typename TP2>
217 tuple_copy (TP1 & a, TP2 && b)
219 (amrex::get<I>(a) = amrex::get<I>(std::forward<TP2>(b)),
220 tuple_copy<I+1,N>(a,std::forward<TP2>(b)));
223 template <std::
size_t I, std::
size_t N,
typename TP1,
typename TP2>
227 tuple_copy (TP1 & a, TP2 && b)
229 amrex::get<I>(a) = amrex::get<I>(std::forward<TP2>(b));
234template <
typename... Ts>
235template <
typename... Us>
239 static_assert(
sizeof...(Us) ==
sizeof...(Ts));
240 detail::tuple_copy<0,
sizeof...(Ts)>(*
this, rhs);
244template <
typename... Ts>
245template <
typename... Us>
249 static_assert(
sizeof...(Us) ==
sizeof...(Ts));
250 detail::tuple_copy<0,
sizeof...(Ts)>(*
this, std::move(rhs));
258 template <
typename T>
struct unwrap {
using type = T; };
259 template <
typename T>
struct unwrap<std::reference_wrapper<T> > {
using type = T&; };
260 template <
typename T>
261 using tuple_decay_t =
typename unwrap<std::decay_t<T>>::type;
265template <
typename... Ts>
268GpuTuple<detail::tuple_decay_t<Ts>...>
276 template <
typename...>
struct tuple_cat_result {};
278 template <
typename... Ts>
279 struct tuple_cat_result<GpuTuple<Ts...> >
281 using type = GpuTuple<Ts...>;
284 template <
typename... T1s,
typename... T2s,
typename... TPs>
285 struct tuple_cat_result<GpuTuple<T1s...>,GpuTuple<T2s...>,TPs...>
287 using type =
typename tuple_cat_result<GpuTuple<T1s..., T2s...>, TPs...>::type;
291 template <
typename R,
typename TP1,
typename TP2, std::size_t... N1, std::size_t... N2>
293 make_tuple (TP1
const& a, TP2
const& b,
294 std::index_sequence<N1...>
const& , std::index_sequence<N2...>
const& )
296 return R(amrex::get<N1>(a)..., amrex::get<N2>(b)...);
303template <
typename TP>
306TupleCat (TP && a) ->
typename detail::tuple_cat_result<detail::tuple_decay_t<TP> >::type
308 using ReturnType =
typename detail::tuple_cat_result<detail::tuple_decay_t<TP> >::type;
309 return ReturnType(std::forward<TP>(a));
312template <
typename TP1,
typename TP2>
315TupleCat (TP1 && a, TP2 && b) ->
typename detail::tuple_cat_result<detail::tuple_decay_t<TP1>,
316 detail::tuple_decay_t<TP2> >::type
318 using ReturnType =
typename detail::tuple_cat_result<detail::tuple_decay_t<TP1>,
319 detail::tuple_decay_t<TP2> >::type;
320 return detail::make_tuple<ReturnType>
321 (std::forward<TP1>(a), std::forward<TP2>(b),
322 std::make_index_sequence<
GpuTupleSize<std::decay_t<TP1>>::value>(),
323 std::make_index_sequence<
GpuTupleSize<std::decay_t<TP2>>::value>());
326template <
typename TP1,
typename TP2,
typename... TPs>
330 ->
typename detail::tuple_cat_result<detail::tuple_decay_t<TP1>,
331 detail::tuple_decay_t<TP2>,
332 detail::tuple_decay_t<TPs>...>::type
335 std::forward<TPs>(args)...);
343 template<std::size_t...Is>
344 struct SplitIndexList {
345 template<std::
size_t J>
347 static constexpr std::size_t get () noexcept {
348 std::size_t arr[
sizeof...(Is)] = {Is...};
352 template<std::
size_t J>
354 static constexpr std::size_t get_exclusive_sum () noexcept {
355 std::size_t arr[
sizeof...(Is)] = {Is...};
357 for (std::size_t k=0; k<J; ++k) {
364 template <std::size_t start,
typename... Args, std::size_t... Is>
367 GetSubTuple (
const GpuTuple<Args...>& tup, std::index_sequence<Is...>)
noexcept
369 return makeTuple(amrex::get<start+Is>(tup)...);
372 template <
typename... Args, std::size_t... Is,
typename SIL>
375 TupleSplitImp (
const GpuTuple<Args...>& tup, std::index_sequence<Is...>, SIL)
noexcept
378 GetSubTuple<(SIL::template get_exclusive_sum<Is>())>(
380 std::make_index_sequence<SIL::template get<Is>()>()
391template <std::size_t... Is,
typename... Args>
396 static_assert((0 + ... + Is) ==
sizeof...(Args),
"Incorrect total size in TupleSplit");
397 return detail::TupleSplitImp(
399 std::make_index_sequence<
sizeof...(Is)>(),
400 detail::SplitIndexList<Is...>()
409 template <
typename F,
typename... Args>
411 auto INVOKE (
F&& f, Args&&... args) ->
decltype(f(std::forward<Args>(args)...));
413 template <
typename V,
typename F,
typename... Args>
struct invoke_result {};
415 template <
typename F,
typename... Args>
416 struct invoke_result<decltype(void(INVOKE(std::declval<F>(), std::declval<Args>()...))),
419 using type =
decltype(INVOKE(std::declval<F>(), std::declval<Args>()...));
422 template <
typename F,
typename...>
struct apply_result {};
424 template <
typename F,
typename... Ts>
425 struct apply_result<
F, GpuTuple<Ts...> >
427 using type =
typename invoke_result<void,
F, Ts...>::type;
430 template <
typename F,
typename TP, std::size_t... N>
433 apply_impl (
F&& f, TP&& t, std::index_sequence<N...> )
434 ->
typename detail::apply_result<F,detail::tuple_decay_t<TP> >::type
436 return std::forward<F>(f)(amrex::get<N>(std::forward<TP>(t))...);
441template <
typename F,
typename TP>
444Apply (
F&& f, TP&& t) ->
typename detail::apply_result<F,detail::tuple_decay_t<TP> >::type
446 return detail::apply_impl(std::forward<F>(f), std::forward<TP>(t),
447 std::make_index_sequence<
GpuTupleSize<std::decay_t<TP>>::value>());
452template <
typename... Args>
454constexpr GpuTuple<Args&...>
455Tie (Args&... args)
noexcept
462template <
typename... Ts>
464constexpr GpuTuple<Ts&&...>
467 return GpuTuple<Ts&&...>(std::forward<Ts>(args)...);
476template <
typename... Ts>
478constexpr GpuTuple<Ts...>
481 return GpuTuple<Ts...>(
static_cast<Ts
>(0)...);
486 template <
typename T, std::size_t... I>
488 auto tuple_to_array_helper (T
const& tup, std::index_sequence<I...>) {
489 return GpuArray<typename GpuTupleElement<0,T>::type,
sizeof...(I)>{amrex::get<I>(tup)...};
502template <
typename T,
typename T2,
typename... Ts>
503requires (Same<T,T2,Ts...>::value)
507 return detail::tuple_to_array_helper(tup, std::index_sequence_for<T,T2,Ts...>{});
513template<
typename... Ts>
514struct std::tuple_size<
amrex::GpuTuple<Ts...>> {
515 static constexpr std::size_t value =
sizeof...(Ts);
519template<
typename T,
typename... Ts>
524template<std::size_t s,
typename T,
typename... Ts>
525struct std::tuple_element<s,
amrex::GpuTuple<T, Ts...>> {
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
GPU-compatible tuple.
Definition AMReX_Tuple.H:98
__host__ __device__ GpuTuple< Ts... > & operator=(GpuTuple< Us... > const &rhs)
Definition AMReX_Tuple.H:237
__host__ __device__ constexpr GpuTuple()=default
constexpr GpuTuple(Ts const &... args)
Definition AMReX_Tuple.H:103
Definition AMReX_Amr.cpp:50
std::tuple< Ts... > Tuple
Definition AMReX_Tuple.H:18
__host__ __device__ constexpr GpuTuple< Ts... > MakeZeroTuple(GpuTuple< Ts... >) noexcept
Return a GpuTuple containing all zeros. Note that a default-constructed GpuTuple can have uninitializ...
Definition AMReX_Tuple.H:479
__host__ __device__ constexpr GpuTuple< Args &... > Tie(Args &... args) noexcept
Definition AMReX_Tuple.H:455
__host__ __device__ constexpr GpuTuple< detail::tuple_decay_t< Ts >... > makeTuple(Ts &&... args)
Definition AMReX_Tuple.H:269
__host__ __device__ constexpr auto TupleSplit(const GpuTuple< Args... > &tup) noexcept
Returns a GpuTuple of GpuTuples obtained by splitting the input GpuTuple according to the sizes speci...
Definition AMReX_Tuple.H:394
__host__ __device__ constexpr GpuTuple< Ts &&... > ForwardAsTuple(Ts &&... args) noexcept
Definition AMReX_Tuple.H:465
__host__ __device__ constexpr auto Apply(F &&f, IntVectND< dim > const &iv)
Definition AMReX_IntVect.H:1350
__host__ __device__ constexpr auto tupleToArray(GpuTuple< T > const &tup)
Definition AMReX_Tuple.H:496
__host__ __device__ constexpr auto TupleCat(TP &&a) -> typename detail::tuple_cat_result< detail::tuple_decay_t< TP > >::type
Definition AMReX_Tuple.H:306
__host__ __device__ constexpr int get(IntVectND< dim > const &iv) noexcept
Get I'th element of IntVectND<dim>
Definition AMReX_IntVect.H:1334
Fixed-size array that can be used on GPU.
Definition AMReX_Array.H:43
Head type
Definition AMReX_Tuple.H:143
Definition AMReX_Tuple.H:135
Definition AMReX_Tuple.H:127
typename std::tuple_element_t< s-1, amrex::GpuTuple< Ts... > > type
Definition AMReX_Tuple.H:526
T type
Definition AMReX_Tuple.H:521