Block-Structured AMR Software Framework
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
AMReX_Tuple.H
Go to the documentation of this file.
1
2#ifndef AMREX_TUPLE_H_
3#define AMREX_TUPLE_H_
4#include <AMReX_Config.H>
5
6#include <AMReX_Array.H>
7#include <AMReX_Functional.H>
9#include <AMReX_TypeList.H>
10#include <AMReX_TypeTraits.H>
11
12#include <array>
13#include <functional>
14#include <tuple>
15
16namespace amrex {
17 template <class... Ts>
18 using Tuple = std::tuple<Ts...>;
19}
20
21namespace amrex {
22
23namespace detail {
24
25template <std::size_t I, typename T>
27{
28 template <typename U=T, std::enable_if_t<std::is_default_constructible_v<U>,int> = 0>
30 constexpr gpu_tuple_element () {} // NOLINT
31
32 explicit constexpr gpu_tuple_element (T const& a_value)
33 : m_value(a_value)
34 {}
35
36 template <typename U, std::enable_if_t<std::is_convertible_v<U&&,T>,int> = 0>
37 explicit constexpr gpu_tuple_element (U && a_value) // NOLINT(bugprone-forwarding-reference-overload)
38 : m_value(std::forward<U>(a_value))
39 {}
40
42};
43
44template <std::size_t I, typename... Ts> struct gpu_tuple_impl;
45
46template <std::size_t I, typename Head, typename... Tail>
47struct gpu_tuple_impl<I, Head, Tail...>
48 : public gpu_tuple_impl<I+1, Tail...>,
49 public gpu_tuple_element<I, Head>
50{
51 template<typename U=Head, std::enable_if_t<std::is_default_constructible_v<U>,int> = 0>
53 constexpr gpu_tuple_impl () {} // NOLINT
54
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)
58 {}
59
60 template <typename UH, typename... UT, std::enable_if_t<std::is_convertible_v<UH&&,Head>,int> = 0>
61 constexpr gpu_tuple_impl (UH&& a_head, UT &&... a_tail)
62 : gpu_tuple_impl<I+1, Tail...>(std::forward<UT>(a_tail)...),
63 gpu_tuple_element<I, Head>(std::forward<UH>(a_head))
64 {}
65};
66
67template <std::size_t I, typename Head>
68struct gpu_tuple_impl<I, Head>
69 : public gpu_tuple_element<I, Head>
70{
71
72 template<typename U=Head, std::enable_if_t<std::is_default_constructible_v<U>,int> = 0>
74 constexpr gpu_tuple_impl () {} // NOLINT
75
76 explicit constexpr gpu_tuple_impl (Head const& a_head)
77 : gpu_tuple_element<I, Head>(a_head)
78 {}
79
80 template <typename U, std::enable_if_t<std::is_convertible_v<U&&,Head>,int> = 0>
81 explicit constexpr gpu_tuple_impl (U&& a_head) // NOLINT(bugprone-forwarding-reference-overload)
82 : gpu_tuple_element<I, Head>(std::forward<U>(a_head))
83 {}
84};
85
86} // detail
87
88// GpuTuple
89
90template <typename... Ts>
92 : public detail::gpu_tuple_impl<0, Ts...>
93{
94public:
95 AMREX_GPU_HOST_DEVICE // Some versions of nvcc require this in debug build
96 constexpr GpuTuple () = default;
97
98 constexpr GpuTuple (Ts const&... args)
99 : detail::gpu_tuple_impl<0, Ts...>(args...)
100 {}
101
102 template <typename... Us, std::enable_if_t<sizeof...(Us) == sizeof...(Ts),int> = 0>
103 constexpr GpuTuple (Us&&... args)
104 : detail::gpu_tuple_impl<0, Ts...>(std::forward<Us>(args)...)
105 {}
106
107 template <typename... Us, std::enable_if_t<sizeof...(Us) == sizeof...(Ts),int> = 0>
109 inline GpuTuple<Ts...>&
111
112 template <typename... Us, std::enable_if_t<sizeof...(Us) == sizeof...(Ts),int> = 0>
114 inline GpuTuple<Ts...>&
116};
117
118// GpuTupleSize
119
120template <typename T> struct GpuTupleSize;
121
122template <typename... Ts>
123struct GpuTupleSize<GpuTuple<Ts...> >
124 : public std::integral_constant<std::size_t, sizeof...(Ts)> {};
125
126// GpuTupleElement
127
128template <std::size_t I, typename T> struct GpuTupleElement;
129
130template <std::size_t I, typename Head, typename... Tail>
131struct GpuTupleElement<I, GpuTuple<Head, Tail...> >
132 : GpuTupleElement<I-1, GpuTuple<Tail...> > {};
133
134template <typename Head, typename... Tail>
135struct GpuTupleElement<0, GpuTuple<Head, Tail...> > {
136 using type = Head;
137};
138
139// get
140
141namespace detail {
142
143template <std::size_t I, typename... Ts>
145constexpr
146typename GpuTupleElement<I, GpuTuple<Ts...> >::type&
148 <I, typename GpuTupleElement<I, GpuTuple<Ts...> >::type>& te) noexcept
149{
150 return te.m_value;
151}
152
153template <std::size_t I, typename... Ts>
155constexpr
156typename GpuTupleElement<I, GpuTuple<Ts...> >::type const&
158 <I, typename GpuTupleElement<I, GpuTuple<Ts...> >::type> const& te) noexcept
159{
160 return te.m_value;
161}
162
163template <std::size_t I, typename... Ts>
165constexpr
166typename GpuTupleElement<I, GpuTuple<Ts...> >::type &&
168 <I, typename GpuTupleElement<I, GpuTuple<Ts...> >::type> && te) noexcept
169{
170 return std::move(te).m_value;
171}
172
173} // detail
174
175template <std::size_t I, typename... Ts>
177constexpr
178typename GpuTupleElement<I, GpuTuple<Ts...> >::type&
179get (GpuTuple<Ts...>& tup) noexcept
180{
181 return detail::get_impl<I,Ts...>(tup);
182}
183
184template <std::size_t I, typename... Ts>
186constexpr
187typename GpuTupleElement<I, GpuTuple<Ts...> >::type const&
188get (GpuTuple<Ts...> const& tup) noexcept
189{
190 return detail::get_impl<I,Ts...>(tup);
191}
192
193template <std::size_t I, typename... Ts>
195constexpr
196typename GpuTupleElement<I, GpuTuple<Ts...> >::type &&
197get (GpuTuple<Ts...> && tup) noexcept
198{
199 return detail::get_impl<I,Ts...>(std::move(tup));
200}
201
202namespace detail {
203 template <std::size_t I, std::size_t N, typename TP1, typename TP2>
205 std::enable_if_t<(I<N-1),void>
206 tuple_copy (TP1 & a, TP2 && b)
207 {
208 (amrex::get<I>(a) = amrex::get<I>(std::forward<TP2>(b)),
209 tuple_copy<I+1,N>(a,std::forward<TP2>(b)));
210 }
211
212 template <std::size_t I, std::size_t N, typename TP1, typename TP2>
214 std::enable_if_t<I==N-1,void>
215 tuple_copy (TP1 & a, TP2 && b)
216 {
217 amrex::get<I>(a) = amrex::get<I>(std::forward<TP2>(b));
218 }
219}
220
221template <typename... Ts>
222template <typename... Us, std::enable_if_t<sizeof...(Us) == sizeof...(Ts),int> >
223AMREX_GPU_HOST_DEVICE inline GpuTuple<Ts...>&
225{
226 detail::tuple_copy<0,sizeof...(Ts)>(*this, rhs);
227 return *this;
228}
229
230template <typename... Ts>
231template <typename... Us, std::enable_if_t<sizeof...(Us) == sizeof...(Ts),int> >
232AMREX_GPU_HOST_DEVICE inline GpuTuple<Ts...>&
234{
235 detail::tuple_copy<0,sizeof...(Ts)>(*this, std::move(rhs));
236 return *this;
237}
238
239// makeTuple
240
241namespace detail {
242 template <typename T> struct unwrap { using type = T; };
243 template <typename T> struct unwrap<std::reference_wrapper<T> > { using type = T&; };
244 template <typename T>
245 using tuple_decay_t = typename unwrap<std::decay_t<T>>::type;
246}
247
248template <typename... Ts>
250constexpr
252makeTuple (Ts &&... args)
253{
254 return GpuTuple<detail::tuple_decay_t<Ts>...>(std::forward<Ts>(args)...);
255}
256
257namespace detail {
258 template <typename...> struct tuple_cat_result {};
259
260 template <typename... Ts>
262 {
263 using type = GpuTuple<Ts...>;
264 };
265
266 template <typename... T1s, typename... T2s, typename... TPs>
267 struct tuple_cat_result<GpuTuple<T1s...>,GpuTuple<T2s...>,TPs...>
268 {
269 using type = typename tuple_cat_result<GpuTuple<T1s..., T2s...>, TPs...>::type;
270 };
271
272 template <typename R, typename TP1, typename TP2, std::size_t... N1, std::size_t... N2>
273 AMREX_GPU_HOST_DEVICE constexpr R
274 make_tuple (TP1 const& a, TP2 const& b,
275 std::index_sequence<N1...> const& /*n1*/, std::index_sequence<N2...> const& /*n2*/)
276 {
277 return R(amrex::get<N1>(a)..., amrex::get<N2>(b)...);
278 }
279}
280
281// TupleCat
282
283template <typename TP>
285constexpr auto
287{
288 using ReturnType = typename detail::tuple_cat_result<detail::tuple_decay_t<TP> >::type;
289 return ReturnType(std::forward<TP>(a));
290}
291
292template <typename TP1, typename TP2>
294constexpr auto
297{
298 using ReturnType = typename detail::tuple_cat_result<detail::tuple_decay_t<TP1>,
300 return detail::make_tuple<ReturnType>
301 (std::forward<TP1>(a), std::forward<TP2>(b),
302 std::make_index_sequence<GpuTupleSize<std::decay_t<TP1>>::value>(),
303 std::make_index_sequence<GpuTupleSize<std::decay_t<TP2>>::value>());
304}
305
306template <typename TP1, typename TP2, typename... TPs>
308constexpr auto
309TupleCat (TP1&& a, TP2&& b, TPs&&... args)
313{
314 return TupleCat(TupleCat(std::forward<TP1>(a),std::forward<TP2>(b)),
315 std::forward<TPs>(args)...);
316}
317
318// TupleSplit
319
320namespace detail {
321
322 template<std::size_t...Is>
324 template<std::size_t J>
326 static constexpr std::size_t get () noexcept {
327 std::size_t arr[sizeof...(Is)] = {Is...};
328 return arr[J];
329 }
330
331 template<std::size_t J>
333 static constexpr std::size_t get_exclusive_sum () noexcept {
334 std::size_t arr[sizeof...(Is)] = {Is...};
335 std::size_t sum = 0;
336 for (std::size_t k=0; k<J; ++k) {
337 sum += arr[k];
338 }
339 return sum;
340 }
341 };
342
343 template <std::size_t start, typename... Args, std::size_t... Is>
345 constexpr auto
346 GetSubTuple (const GpuTuple<Args...>& tup, std::index_sequence<Is...>) noexcept
347 {
348 return makeTuple(amrex::get<start+Is>(tup)...);
349 }
350
351 template <typename... Args, std::size_t... Is, typename SIL>
353 constexpr auto
354 TupleSplitImp (const GpuTuple<Args...>& tup, std::index_sequence<Is...>, SIL) noexcept
355 {
356 return makeTuple(
357 GetSubTuple<(SIL::template get_exclusive_sum<Is>())>(
358 tup,
359 std::make_index_sequence<SIL::template get<Is>()>()
360 )...
361 );
362 }
363}
364
369template <std::size_t... Is, typename... Args>
371constexpr auto
372TupleSplit (const GpuTuple<Args...>& tup) noexcept
373{
374 static_assert((0 + ... + Is) == sizeof...(Args), "Incorrect total size in TupleSplit");
376 tup,
377 std::make_index_sequence<sizeof...(Is)>(),
379 );
380}
381
382// Apply
383
384namespace detail {
385
386 template <typename F, typename... Args>
388 auto INVOKE (F&& f, Args&&... args) -> decltype(f(std::forward<Args>(args)...));
389
390 template <typename V, typename F, typename... Args> struct invoke_result {};
391
392 template <typename F, typename... Args>
393 struct invoke_result<decltype(void(INVOKE(std::declval<F>(), std::declval<Args>()...))),
394 F, Args...>
395 {
396 using type = decltype(INVOKE(std::declval<F>(), std::declval<Args>()...));
397 };
398
399 template <typename F, typename...> struct apply_result {};
400
401 template <typename F, typename... Ts>
402 struct apply_result<F, GpuTuple<Ts...> >
403 {
404 using type = typename invoke_result<void, F, Ts...>::type;
405 };
406
407 template <typename F, typename TP, std::size_t... N>
409 constexpr auto
410 apply_impl (F&& f, TP&& t, std::index_sequence<N...> /*is*/)
412 {
413 return std::forward<F>(f)(amrex::get<N>(std::forward<TP>(t))...);
414 }
415}
416
417template <typename F, typename TP>
419constexpr auto
421{
422 return detail::apply_impl(std::forward<F>(f), std::forward<TP>(t),
423 std::make_index_sequence<GpuTupleSize<std::decay_t<TP>>::value>());
424}
425
426// Tie
427
428template <typename... Args>
430constexpr GpuTuple<Args&...>
431Tie (Args&... args) noexcept
432{
433 return GpuTuple<Args&...>(args...);
434}
435
436// ForwardAsTuple
437
438template <typename... Ts>
440constexpr GpuTuple<Ts&&...>
441ForwardAsTuple (Ts&&... args) noexcept
442{
443 return GpuTuple<Ts&&...>(std::forward<Ts>(args)...);
444}
445
446// MakeZeroTuple
447
452template <typename... Ts>
454constexpr GpuTuple<Ts...>
456{
457 return GpuTuple<Ts...>(static_cast<Ts>(0)...);
458}
459
460namespace detail {
461 template <typename T, std::size_t... I>
462 AMREX_GPU_HOST_DEVICE constexpr
463 auto tuple_to_array_helper (T const& tup, std::index_sequence<I...>) {
464 return GpuArray<typename GpuTupleElement<0,T>::type, sizeof...(I)>{amrex::get<I>(tup)...};
465 }
466}
467
468template <typename T>
469AMREX_GPU_HOST_DEVICE constexpr
470auto tupleToArray (GpuTuple<T> const& tup)
471{
472 return GpuArray<T,1>{amrex::get<0>(tup)};
473}
474
476template <typename T, typename T2, typename... Ts, std::enable_if_t<Same<T,T2,Ts...>::value, int> = 0>
477AMREX_GPU_HOST_DEVICE constexpr
479{
480 return detail::tuple_to_array_helper(tup, std::index_sequence_for<T,T2,Ts...>{});
481}
482
483} // namespace amrex
484
485// Spcialize std::tuple_size for GpuTuple. Used by structured bindings.
486template<typename... Ts>
487struct std::tuple_size<amrex::GpuTuple<Ts...>> {
488 static constexpr std::size_t value = sizeof...(Ts);
489};
490
491// Spcialize std::tuple_element for GpuTuple. Used by structured bindings.
492template<typename T, typename... Ts>
493struct std::tuple_element<std::size_t{0}, amrex::GpuTuple<T, Ts...>> {
494 using type = T;
495};
496
497template<std::size_t s, typename T, typename... Ts>
498struct std::tuple_element<s, amrex::GpuTuple<T, Ts...>> {
499 using type = typename std::tuple_element<s-1, amrex::GpuTuple<Ts...>>::type;
500};
501
502#endif /*AMREX_TUPLE_H_*/
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
Definition AMReX_Tuple.H:93
AMREX_GPU_HOST_DEVICE constexpr GpuTuple()=default
constexpr GpuTuple(Us &&... args)
Definition AMReX_Tuple.H:103
constexpr GpuTuple(Ts const &... args)
Definition AMReX_Tuple.H:98
AMREX_GPU_HOST_DEVICE GpuTuple< Ts... > & operator=(GpuTuple< Us... > const &rhs)
Definition AMReX_Tuple.H:224
@ sum
Definition AMReX_ParallelReduce.H:19
AMREX_GPU_HOST_DEVICE std::enable_if_t<(I< N-1), void > tuple_copy(TP1 &a, TP2 &&b)
Definition AMReX_Tuple.H:206
AMREX_GPU_HOST_DEVICE constexpr GpuTupleElement< I, GpuTuple< Ts... > >::type & get_impl(detail::gpu_tuple_element< I, typename GpuTupleElement< I, GpuTuple< Ts... > >::type > &te) noexcept
Definition AMReX_Tuple.H:147
AMREX_GPU_HOST_DEVICE constexpr auto TupleSplitImp(const GpuTuple< Args... > &tup, std::index_sequence< Is... >, SIL) noexcept
Definition AMReX_Tuple.H:354
AMREX_GPU_HOST_DEVICE constexpr auto tuple_to_array_helper(T const &tup, std::index_sequence< I... >)
Definition AMReX_Tuple.H:463
AMREX_GPU_HOST_DEVICE constexpr R make_tuple(TP1 const &a, TP2 const &b, std::index_sequence< N1... > const &, std::index_sequence< N2... > const &)
Definition AMReX_Tuple.H:274
typename unwrap< std::decay_t< T > >::type tuple_decay_t
Definition AMReX_Tuple.H:245
AMREX_GPU_HOST_DEVICE constexpr auto GetSubTuple(const GpuTuple< Args... > &tup, std::index_sequence< Is... >) noexcept
Definition AMReX_Tuple.H:346
AMREX_GPU_HOST_DEVICE constexpr auto apply_impl(F &&f, TP &&t, std::index_sequence< N... >) -> typename detail::apply_result< F, detail::tuple_decay_t< TP > >::type
Definition AMReX_Tuple.H:410
AMREX_GPU_HOST_DEVICE auto INVOKE(F &&f, Args &&... args) -> decltype(f(std::forward< Args >(args)...))
Definition AMReX_Amr.cpp:49
std::tuple< Ts... > Tuple
Definition AMReX_Tuple.H:18
AMREX_GPU_HOST_DEVICE constexpr GpuTuple< Ts &&... > ForwardAsTuple(Ts &&... args) noexcept
Definition AMReX_Tuple.H:441
AMREX_GPU_HOST_DEVICE constexpr GpuTuple< Args &... > Tie(Args &... args) noexcept
Definition AMReX_Tuple.H:431
AMREX_GPU_HOST_DEVICE constexpr GpuTupleElement< I, GpuTuple< Ts... > >::type & get(GpuTuple< Ts... > &tup) noexcept
Definition AMReX_Tuple.H:179
AMREX_GPU_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:455
AMREX_GPU_HOST_DEVICE constexpr auto Apply(F &&f, TP &&t) -> typename detail::apply_result< F, detail::tuple_decay_t< TP > >::type
Definition AMReX_Tuple.H:420
AMREX_GPU_HOST_DEVICE constexpr GpuTuple< detail::tuple_decay_t< Ts >... > makeTuple(Ts &&... args)
Definition AMReX_Tuple.H:252
AMREX_GPU_HOST_DEVICE constexpr auto tupleToArray(GpuTuple< T > const &tup)
Definition AMReX_Tuple.H:470
AMREX_GPU_HOST_DEVICE constexpr auto TupleCat(TP &&a) -> typename detail::tuple_cat_result< detail::tuple_decay_t< TP > >::type
Definition AMReX_Tuple.H:286
AMREX_GPU_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:372
Definition AMReX_FabArrayCommI.H:896
Definition AMReX_Array.H:34
Definition AMReX_Tuple.H:128
Definition AMReX_Tuple.H:120
Definition AMReX_Tuple.H:323
static AMREX_GPU_HOST_DEVICE constexpr std::size_t get_exclusive_sum() noexcept
Definition AMReX_Tuple.H:333
static AMREX_GPU_HOST_DEVICE constexpr std::size_t get() noexcept
Definition AMReX_Tuple.H:326
typename invoke_result< void, F, Ts... >::type type
Definition AMReX_Tuple.H:404
Definition AMReX_Tuple.H:399
Definition AMReX_Tuple.H:27
constexpr gpu_tuple_element(U &&a_value)
Definition AMReX_Tuple.H:37
T m_value
Definition AMReX_Tuple.H:41
constexpr gpu_tuple_element(T const &a_value)
Definition AMReX_Tuple.H:32
AMREX_GPU_HOST_DEVICE constexpr gpu_tuple_element()
Definition AMReX_Tuple.H:30
AMREX_GPU_HOST_DEVICE constexpr gpu_tuple_impl()
Definition AMReX_Tuple.H:53
constexpr gpu_tuple_impl(Head const &a_head, Tail const &... a_tail)
Definition AMReX_Tuple.H:55
constexpr gpu_tuple_impl(UH &&a_head, UT &&... a_tail)
Definition AMReX_Tuple.H:61
AMREX_GPU_HOST_DEVICE constexpr gpu_tuple_impl()
Definition AMReX_Tuple.H:74
constexpr gpu_tuple_impl(Head const &a_head)
Definition AMReX_Tuple.H:76
constexpr gpu_tuple_impl(U &&a_head)
Definition AMReX_Tuple.H:81
Definition AMReX_Tuple.H:44
decltype(INVOKE(std::declval< F >(), std::declval< Args >()...)) type
Definition AMReX_Tuple.H:396
Definition AMReX_Tuple.H:390
typename tuple_cat_result< GpuTuple< T1s..., T2s... >, TPs... >::type type
Definition AMReX_Tuple.H:269
Definition AMReX_Tuple.H:258
Definition AMReX_Tuple.H:242
T type
Definition AMReX_Tuple.H:242
typename std::tuple_element< s-1, amrex::GpuTuple< Ts... > >::type type
Definition AMReX_Tuple.H:499