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>) {}
38 explicit constexpr gpu_tuple_element (T
const& a_value)
43 requires (std::is_convertible_v<U&&,T>)
44 explicit constexpr gpu_tuple_element (U && a_value)
45 : m_value(std::forward<U>(a_value))
51template <std::size_t I,
typename... Ts>
struct gpu_tuple_impl;
53template <std::size_t I,
typename Head,
typename... Tail>
54struct gpu_tuple_impl<I, Head, Tail...>
55 :
public gpu_tuple_impl<I+1, Tail...>,
56 public gpu_tuple_element<I, Head>
59 constexpr gpu_tuple_impl ()
requires (std::is_default_constructible_v<Head>) {}
61 constexpr gpu_tuple_impl (Head
const& a_head, Tail
const&... a_tail)
62 : gpu_tuple_impl<I+1, Tail...>(a_tail...),
63 gpu_tuple_element<I, Head>(a_head)
66 template <
typename UH,
typename... UT>
67 requires (std::is_convertible_v<UH&&,Head>)
68 constexpr gpu_tuple_impl (UH&& a_head, UT &&... a_tail)
69 : gpu_tuple_impl<I+1, Tail...>(std::forward<UT>(a_tail)...),
70 gpu_tuple_element<I, Head>(std::forward<UH>(a_head))
74template <std::
size_t I,
typename Head>
75struct gpu_tuple_impl<I, Head>
76 :
public gpu_tuple_element<I, Head>
80 constexpr gpu_tuple_impl ()
requires (std::is_default_constructible_v<Head>) {}
82 explicit constexpr gpu_tuple_impl (Head
const& a_head)
83 : gpu_tuple_element<I, Head>(a_head)
87 requires (std::is_convertible_v<U&&,Head>)
88 explicit constexpr gpu_tuple_impl (U&& a_head)
89 : gpu_tuple_element<I, Head>(std::forward<U>(a_head))
101template <
typename... Ts>
103 :
public detail::gpu_tuple_impl<0, Ts...>
110 : detail::gpu_tuple_impl<0, Ts...>(args...)
113 template <
typename... Us>
114 requires (
sizeof...(Us) ==
sizeof...(Ts))
116 : detail::gpu_tuple_impl<0, Ts...>(std::forward<Us>(args)...)
119 template <
typename... Us>
125 template <
typename... Us>
135template <
typename... Ts>
137 :
public std::integral_constant<std::size_t, sizeof...(Ts)> {};
143template <std::size_t I,
typename Head,
typename... Tail>
147template <
typename Head,
typename... Tail>
157template <std::size_t I,
typename... Ts>
161get_impl (detail::gpu_tuple_element
167template <std::size_t I,
typename... Ts>
170typename GpuTupleElement<I, GpuTuple<Ts...> >::type
const&
171get_impl (detail::gpu_tuple_element
172 <I,
typename GpuTupleElement<I, GpuTuple<Ts...> >::type>
const& te)
noexcept
177template <std::size_t I,
typename... Ts>
180typename GpuTupleElement<I, GpuTuple<Ts...> >::type &&
181get_impl (detail::gpu_tuple_element
182 <I,
typename GpuTupleElement<I, GpuTuple<Ts...> >::type> && te)
noexcept
184 return std::move(te).m_value;
190template <std::size_t I,
typename... Ts>
193typename GpuTupleElement<I, GpuTuple<Ts...> >::type&
196 return detail::get_impl<I,Ts...>(tup);
199template <std::size_t I,
typename... Ts>
202typename GpuTupleElement<I, GpuTuple<Ts...> >::type
const&
205 return detail::get_impl<I,Ts...>(tup);
208template <std::size_t I,
typename... Ts>
211typename GpuTupleElement<I, GpuTuple<Ts...> >::type &&
214 return detail::get_impl<I,Ts...>(std::move(tup));
219 template <std::
size_t I, std::
size_t N,
typename TP1,
typename TP2>
223 tuple_copy (TP1 & a, TP2 && b)
225 (amrex::get<I>(a) = amrex::get<I>(std::forward<TP2>(b)),
226 tuple_copy<I+1,N>(a,std::forward<TP2>(b)));
229 template <std::
size_t I, std::
size_t N,
typename TP1,
typename TP2>
233 tuple_copy (TP1 & a, TP2 && b)
235 amrex::get<I>(a) = amrex::get<I>(std::forward<TP2>(b));
240template <
typename... Ts>
241template <
typename... Us>
245 static_assert(
sizeof...(Us) ==
sizeof...(Ts));
246 detail::tuple_copy<0,
sizeof...(Ts)>(*
this, rhs);
250template <
typename... Ts>
251template <
typename... Us>
255 static_assert(
sizeof...(Us) ==
sizeof...(Ts));
256 detail::tuple_copy<0,
sizeof...(Ts)>(*
this, std::move(rhs));
264 template <
typename T>
struct unwrap {
using type = T; };
265 template <
typename T>
struct unwrap<std::reference_wrapper<T> > {
using type = T&; };
266 template <
typename T>
267 using tuple_decay_t =
typename unwrap<std::decay_t<T>>::type;
271template <
typename... Ts>
274GpuTuple<detail::tuple_decay_t<Ts>...>
282 template <
typename...>
struct tuple_cat_result {};
284 template <
typename... Ts>
285 struct tuple_cat_result<GpuTuple<Ts...> >
287 using type = GpuTuple<Ts...>;
290 template <
typename... T1s,
typename... T2s,
typename... TPs>
291 struct tuple_cat_result<GpuTuple<T1s...>,GpuTuple<T2s...>,TPs...>
293 using type =
typename tuple_cat_result<GpuTuple<T1s..., T2s...>, TPs...>::type;
297 template <
typename R,
typename TP1,
typename TP2, std::size_t... N1, std::size_t... N2>
299 make_tuple (TP1
const& a, TP2
const& b,
300 std::index_sequence<N1...>
const& , std::index_sequence<N2...>
const& )
302 return R(amrex::get<N1>(a)..., amrex::get<N2>(b)...);
309template <
typename TP>
312TupleCat (TP && a) ->
typename detail::tuple_cat_result<detail::tuple_decay_t<TP> >::type
314 using ReturnType =
typename detail::tuple_cat_result<detail::tuple_decay_t<TP> >::type;
315 return ReturnType(std::forward<TP>(a));
318template <
typename TP1,
typename TP2>
321TupleCat (TP1 && a, TP2 && b) ->
typename detail::tuple_cat_result<detail::tuple_decay_t<TP1>,
322 detail::tuple_decay_t<TP2> >::type
324 using ReturnType =
typename detail::tuple_cat_result<detail::tuple_decay_t<TP1>,
325 detail::tuple_decay_t<TP2> >::type;
326 return detail::make_tuple<ReturnType>
327 (std::forward<TP1>(a), std::forward<TP2>(b),
328 std::make_index_sequence<
GpuTupleSize<std::decay_t<TP1>>::value>(),
329 std::make_index_sequence<
GpuTupleSize<std::decay_t<TP2>>::value>());
332template <
typename TP1,
typename TP2,
typename... TPs>
336 ->
typename detail::tuple_cat_result<detail::tuple_decay_t<TP1>,
337 detail::tuple_decay_t<TP2>,
338 detail::tuple_decay_t<TPs>...>::type
341 std::forward<TPs>(args)...);
349 template<std::size_t...Is>
350 struct SplitIndexList {
351 template<std::
size_t J>
353 static constexpr std::size_t get () noexcept {
354 std::size_t arr[
sizeof...(Is)] = {Is...};
358 template<std::
size_t J>
360 static constexpr std::size_t get_exclusive_sum () noexcept {
361 std::size_t arr[
sizeof...(Is)] = {Is...};
363 for (std::size_t k=0; k<J; ++k) {
370 template <std::size_t start,
typename... Args, std::size_t... Is>
373 GetSubTuple (
const GpuTuple<Args...>& tup, std::index_sequence<Is...>)
noexcept
375 return makeTuple(amrex::get<start+Is>(tup)...);
378 template <
typename... Args, std::size_t... Is,
typename SIL>
381 TupleSplitImp (
const GpuTuple<Args...>& tup, std::index_sequence<Is...>, SIL)
noexcept
384 GetSubTuple<(SIL::template get_exclusive_sum<Is>())>(
386 std::make_index_sequence<SIL::template get<Is>()>()
397template <std::size_t... Is,
typename... Args>
402 static_assert((0 + ... + Is) ==
sizeof...(Args),
"Incorrect total size in TupleSplit");
403 return detail::TupleSplitImp(
405 std::make_index_sequence<
sizeof...(Is)>(),
406 detail::SplitIndexList<Is...>()
415 template <
typename F,
typename... Args>
417 auto INVOKE (
F&& f, Args&&... args) ->
decltype(f(std::forward<Args>(args)...));
419 template <
typename V,
typename F,
typename... Args>
struct invoke_result {};
421 template <
typename F,
typename... Args>
422 struct invoke_result<decltype(void(INVOKE(std::declval<F>(), std::declval<Args>()...))),
425 using type =
decltype(INVOKE(std::declval<F>(), std::declval<Args>()...));
428 template <
typename F,
typename...>
struct apply_result {};
430 template <
typename F,
typename... Ts>
431 struct apply_result<
F, GpuTuple<Ts...> >
433 using type =
typename invoke_result<void,
F, Ts...>::type;
436 template <
typename F,
typename TP, std::size_t... N>
439 apply_impl (
F&& f, TP&& t, std::index_sequence<N...> )
440 ->
typename detail::apply_result<F,detail::tuple_decay_t<TP> >::type
442 return std::forward<F>(f)(amrex::get<N>(std::forward<TP>(t))...);
447template <
typename F,
typename TP>
450Apply (
F&& f, TP&& t) ->
typename detail::apply_result<F,detail::tuple_decay_t<TP> >::type
452 return detail::apply_impl(std::forward<F>(f), std::forward<TP>(t),
453 std::make_index_sequence<
GpuTupleSize<std::decay_t<TP>>::value>());
458template <
typename... Args>
460constexpr GpuTuple<Args&...>
461Tie (Args&... args)
noexcept
468template <
typename... Ts>
470constexpr GpuTuple<Ts&&...>
473 return GpuTuple<Ts&&...>(std::forward<Ts>(args)...);
482template <
typename... Ts>
484constexpr GpuTuple<Ts...>
487 return GpuTuple<Ts...>(
static_cast<Ts
>(0)...);
492 template <
typename T, std::size_t... I>
494 auto tuple_to_array_helper (T
const& tup, std::index_sequence<I...>) {
495 return GpuArray<typename GpuTupleElement<0,T>::type,
sizeof...(I)>{amrex::get<I>(tup)...};
508template <
typename T,
typename T2,
typename... Ts>
509requires (Same<T,T2,Ts...>::value)
513 return detail::tuple_to_array_helper(tup, std::index_sequence_for<T,T2,Ts...>{});
519template<
typename... Ts>
520struct std::tuple_size<
amrex::GpuTuple<Ts...>> {
521 static constexpr std::size_t value =
sizeof...(Ts);
525template<
typename T,
typename... Ts>
530template<std::size_t s,
typename T,
typename... Ts>
531struct std::tuple_element<s,
amrex::GpuTuple<T, Ts...>> {
Fixed-size array types for use on GPU and CPU.
Function object (functor) types for use with reductions and transforms.
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
GPU-compatible tuple.
Definition AMReX_Tuple.H:104
__host__ __device__ GpuTuple< Ts... > & operator=(GpuTuple< Us... > const &rhs)
Definition AMReX_Tuple.H:243
__host__ __device__ constexpr GpuTuple()=default
constexpr GpuTuple(Ts const &... args)
Definition AMReX_Tuple.H:109
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:485
__host__ __device__ constexpr GpuTuple< Args &... > Tie(Args &... args) noexcept
Definition AMReX_Tuple.H:461
__host__ __device__ constexpr GpuTuple< detail::tuple_decay_t< Ts >... > makeTuple(Ts &&... args)
Definition AMReX_Tuple.H:275
__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:400
__host__ __device__ constexpr GpuTuple< Ts &&... > ForwardAsTuple(Ts &&... args) noexcept
Definition AMReX_Tuple.H:471
__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:502
__host__ __device__ constexpr auto TupleCat(TP &&a) -> typename detail::tuple_cat_result< detail::tuple_decay_t< TP > >::type
Definition AMReX_Tuple.H:312
__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:52
Head type
Definition AMReX_Tuple.H:149
Definition AMReX_Tuple.H:141
Definition AMReX_Tuple.H:133
typename std::tuple_element_t< s-1, amrex::GpuTuple< Ts... > > type
Definition AMReX_Tuple.H:532
T type
Definition AMReX_Tuple.H:527