IPPL (Independent Parallel Particle Layer)
IPPL
Loading...
Searching...
No Matches
Tuple.h
Go to the documentation of this file.
1//
2// Class Tuple
3// Tuple class used for fixed-size containers containing objects of different types, e.g.
4// different KOKKOS_LAMBDAs
5//
6#ifndef IPPL_Tuple_H
7#define IPPL_Tuple_H
8#include <Kokkos_Macros.hpp>
9#include <concepts>
10#include <cstddef>
11#include <functional>
12#include <type_traits>
13#include <utility>
14
15namespace ippl {
19
27 template <std::size_t i, std::size_t N, typename... Ts>
28 struct TupleImpl;
38 template <std::size_t i, std::size_t N, typename T, typename R, typename... Ts>
39 struct TupleImpl<i, N, T, R, Ts...> /* : TupleImpl<i + 1, N, R, Ts...> */ {
45 TupleImpl<i + 1, N, R, Ts...> next;
46 template <std::size_t Idx>
47 requires(Idx < N)
48 KOKKOS_INLINE_FUNCTION auto& get() noexcept {
49 if constexpr (Idx == i) {
50 return val;
51 } else {
52 return next.template get<Idx>();
53 }
54 }
55 template <std::size_t Idx>
56 requires(Idx < N)
57 KOKKOS_INLINE_FUNCTION const auto& get() const noexcept {
58 if constexpr (Idx == i) {
59 return val;
60 } else {
61 return next.template get<Idx>();
62 }
63 }
65 requires(std::is_copy_assignable_v<T> && std::is_copy_assignable_v<R>
66 && (std::is_copy_assignable_v<Ts> && ...))
67 = default;
69 requires(std::is_move_assignable_v<T> && std::is_move_assignable_v<R>
70 && (std::is_move_assignable_v<Ts> && ...))
71 = default;
73 requires(std::is_copy_constructible_v<T> && std::is_copy_constructible_v<R>
74 && (std::is_copy_constructible_v<Ts> && ...))
75 = default;
77 requires(std::is_move_constructible_v<T> && std::is_move_constructible_v<R>
78 && (std::is_move_constructible_v<Ts> && ...))
79 = default;
80
82 requires(std::is_default_constructible_v<T> && std::is_default_constructible_v<R>
83 && (std::is_default_constructible_v<Ts> && ...))
84 = default;
85 template <typename CtorT, typename CtorR, typename... CtorTs>
86 KOKKOS_INLINE_FUNCTION TupleImpl(CtorT&& t, CtorR&& r, CtorTs&&... ts)
87 : val(std::forward<T>(t))
88 , next(std::forward<CtorR>(r), std::forward<CtorTs>(ts)...) {}
89 };
90
97 template <std::size_t i, std::size_t N, typename T>
98 struct TupleImpl<i, N, T> {
100 template <std::size_t Idx>
101 requires(Idx == N - 1)
102 KOKKOS_INLINE_FUNCTION auto& get() noexcept {
103 return val;
104 }
105 template <std::size_t Idx>
106 requires(Idx == N - 1)
107 KOKKOS_INLINE_FUNCTION const auto& get() const noexcept {
108 return val;
109 }
111 requires(std::is_default_constructible_v<T>)
112 = default;
113 KOKKOS_INLINE_FUNCTION TupleImpl(const T& t)
114 : val(t) {}
115 KOKKOS_INLINE_FUNCTION TupleImpl(T&& t)
116 : val(std::forward<T>(t)) {}
117 };
118
123 template <typename... Ts>
124 struct Tuple {
125 private:
126 TupleImpl<0, sizeof...(Ts), Ts...> tupleImpl_m;
127
128 public:
129 constexpr static std::size_t dim = sizeof...(Ts);
130 constexpr static std::size_t size = sizeof...(Ts);
131 template <std::size_t Idx>
132 requires(Idx < sizeof...(Ts))
133 KOKKOS_INLINE_FUNCTION auto&& get() noexcept {
134 return tupleImpl_m.template get<Idx>();
135 }
136 template <std::size_t Idx>
137 requires(Idx < sizeof...(Ts))
138 KOKKOS_INLINE_FUNCTION auto&& get() const noexcept {
139 return tupleImpl_m.template get<Idx>();
140 }
141 template <typename Functor, std::size_t Idx, typename... OtherTs>
142 KOKKOS_INLINE_FUNCTION int applySingle(Functor func, const Tuple<OtherTs...>& other)
143 requires(std::is_copy_assignable_v<Ts> && ...)
144 {
145 func(get<Idx>(), other.template get<Idx>());
146 return Idx; // Dummy
147 }
148 template <typename Functor, typename... OtherTs, std::size_t... Idx>
149 KOKKOS_INLINE_FUNCTION void applySequence(Functor func, const Tuple<OtherTs...>& other,
150 const std::index_sequence<Idx...>&) {
151 int val = (applySingle<Functor, Idx, OtherTs...>(func, other) ^ ...);
152 (void)val; // Dummy for ^
153 }
154 template <std::size_t Idx, typename... OtherTs>
155 KOKKOS_INLINE_FUNCTION int assignToSingle(const Tuple<OtherTs...>& other)
156 requires(std::is_copy_assignable_v<Ts> && ...)
157 {
158 (get<Idx>() = other.template get<Idx>());
159 return Idx; // Dummy
160 }
161 template <typename... OtherTs, std::size_t... Idx>
162 KOKKOS_INLINE_FUNCTION void assignToSequence(const Tuple<OtherTs...>& other,
163 const std::index_sequence<Idx...>&)
164 requires(std::is_copy_assignable_v<Ts> && ...)
165 {
166 int val = (assignToSingle<Idx, OtherTs...>(other) ^ ...);
167 (void)val; // Dummy for ^
168 }
169 template <std::size_t Idx, typename... OtherTs>
170 KOKKOS_INLINE_FUNCTION int assignToSingle(Tuple<OtherTs...>&& other)
171 requires(std::is_move_assignable_v<Ts> && ...)
172 {
173 (get<Idx>() = std::move(other.template get<Idx>()));
174 return Idx; // Dummy
175 }
176 template <typename... OtherTs, std::size_t... Idx>
177 KOKKOS_INLINE_FUNCTION void assignToSequence(Tuple<OtherTs...>&& other,
178 const std::index_sequence<Idx...>&)
179 requires(std::is_move_assignable_v<Ts> && ...)
180 {
181 int val = (assignToSingle<Idx, OtherTs...>(std::move(other)) ^ ...);
182 (void)val; // Dummy for ^
183 }
184 template <typename... OtherTs>
185 KOKKOS_INLINE_FUNCTION Tuple& operator=(const Tuple<OtherTs...>& other)
186 requires(std::is_copy_assignable_v<Ts> && ...)
187 {
188 assignToSequence(other, std::make_index_sequence<sizeof...(Ts)>{});
189 return *this;
190 }
191
192 template <typename... OtherTs>
193 KOKKOS_INLINE_FUNCTION Tuple& operator=(Tuple<OtherTs...>&& other)
194 requires(std::is_move_assignable_v<Ts> && ...)
195 {
196 assignToSequence(std::move(other), std::make_index_sequence<sizeof...(Ts)>{});
197 return *this;
198 }
199 KOKKOS_INLINE_FUNCTION Tuple& operator+=(const Tuple& other)
200 requires(std::is_arithmetic_v<Ts> && ...)
201 {
203 KOKKOS_LAMBDA(auto& x, const auto& y) { x += y; }, other,
204 std::make_index_sequence<sizeof...(Ts)>{});
205 return *this;
206 }
207 KOKKOS_INLINE_FUNCTION Tuple& operator-=(const Tuple& other)
208 requires(std::is_arithmetic_v<Ts> && ...)
209 {
211 KOKKOS_LAMBDA(auto& x, const auto& y) { x -= y; }, other,
212 std::make_index_sequence<sizeof...(Ts)>{});
213 return *this;
214 }
215 KOKKOS_INLINE_FUNCTION Tuple& operator*=(const Tuple& other)
216 requires(std::is_arithmetic_v<Ts> && ...)
217 {
219 KOKKOS_LAMBDA(auto& x, const auto& y) { x *= y; }, other,
220 std::make_index_sequence<sizeof...(Ts)>{});
221 return *this;
222 }
223 KOKKOS_INLINE_FUNCTION Tuple& operator/=(const Tuple& other)
224 requires(std::is_arithmetic_v<Ts> && ...)
225 {
227 KOKKOS_LAMBDA(auto& x, const auto& y) { x /= y; }, other,
228 std::make_index_sequence<sizeof...(Ts)>{});
229 return *this;
230 }
231 KOKKOS_INLINE_FUNCTION Tuple operator+(const Tuple& other) const
232 requires(std::is_arithmetic_v<Ts> && ...)
233 {
234 return Tuple(Tuple(*this) += other);
235 }
236 KOKKOS_INLINE_FUNCTION Tuple operator-(const Tuple& other) const
237 requires(std::is_arithmetic_v<Ts> && ...)
238 {
239 return Tuple(Tuple(*this) -= other);
240 }
241 KOKKOS_INLINE_FUNCTION Tuple operator*(const Tuple& other) const
242 requires(std::is_arithmetic_v<Ts> && ...)
243 {
244 return Tuple(Tuple(*this) *= other);
245 }
246 KOKKOS_INLINE_FUNCTION Tuple operator/(const Tuple& other) const
247 requires(std::is_arithmetic_v<Ts> && ...)
248 {
249 return Tuple(Tuple(*this) /= other);
250 }
251 template <std::size_t Idx, std::size_t N, typename... OtherTs>
252 KOKKOS_INLINE_FUNCTION bool lexicographicalLess(const Tuple& other) const {
253 if constexpr (Idx == N) {
254 return false;
255 } else {
256 return (get<Idx>() < other.template get<Idx>())
257 ? true
258 : lexicographicalLess<Idx + 1, N, OtherTs...>(other);
259 }
260 }
261 template <std::size_t Idx, std::size_t N, typename... OtherTs>
262 KOKKOS_INLINE_FUNCTION bool lexicographicalEquals(const Tuple& other) const {
263 if constexpr (Idx == N) {
264 return true;
265 } else {
266 return (get<Idx>() == other.template get<Idx>())
267 && lexicographicalEquals<Idx + 1, N, OtherTs...>(other);
268 }
269 }
270 template <typename... OtherTs>
271 KOKKOS_INLINE_FUNCTION bool operator<(const Tuple<OtherTs...>& other) const
272 requires((sizeof...(Ts) == sizeof...(OtherTs)) && (std::totally_ordered<Ts> && ...))
273 {
274 return lexicographicalLess<0, sizeof...(Ts), OtherTs...>(other);
275 }
276 template <typename... OtherTs>
277 KOKKOS_INLINE_FUNCTION bool operator==(const Tuple<OtherTs...>& other) const
278 requires((sizeof...(Ts) == sizeof...(OtherTs)) && (std::totally_ordered<Ts> && ...))
279 {
280 return lexicographicalEquals<0, sizeof...(Ts)>(other);
281 }
283 requires(std::is_copy_assignable_v<Ts> && ...)
284 = default;
285
287 requires(std::is_move_assignable_v<Ts> && ...)
288 = default;
289
291 requires(std::is_copy_constructible_v<Ts> && ...)
292 = default;
294 requires(std::is_move_constructible_v<Ts> && ...)
295 = default;
296
298 requires(std::is_default_constructible_v<Ts> && ...)
299 = default;
300 template <typename... CtorTs>
301 requires(std::constructible_from<Ts, CtorTs> && ...)
302 KOKKOS_INLINE_FUNCTION Tuple(CtorTs&&... args)
303 : tupleImpl_m(std::forward<Ts>(args)...) {}
304 };
305
313 template <std::size_t Idx, typename... Ts>
314 KOKKOS_INLINE_FUNCTION auto& get(Tuple<Ts...>& t) {
315 return t.template get<Idx>();
316 }
317
325 template <std::size_t Idx, typename... Ts>
326 KOKKOS_INLINE_FUNCTION const auto& get(const Tuple<Ts...>& t) {
327 return t.template get<Idx>();
328 }
329
336 template <typename... Ts>
337 KOKKOS_INLINE_FUNCTION Tuple<Ts...> makeTuple(Ts&&... args) {
338 return Tuple<Ts...>(std::forward<Ts>(args)...);
339 }
340 template <std::size_t Idx, typename T, typename... Ts>
342 using type = TupleTypeImpl<Idx - 1, Ts...>;
343 };
344 template <typename T, typename... Ts>
345 struct TupleTypeImpl<0, T, Ts...> {
346 using type = T;
347 };
348 template <std::size_t Idx, typename... Ts>
349 using TupleType = typename TupleTypeImpl<Idx, Ts...>::type;
350} // namespace ippl
351
352namespace std {
353 template <typename... Ts>
354 struct tuple_size<::ippl::Tuple<Ts...>> : std::integral_constant<size_t, sizeof...(Ts)> {};
355
356 template <size_t Idx, typename... Ts>
357 struct tuple_element<Idx, ::ippl::Tuple<Ts...>> {
358 using type = typename ::ippl::TupleType<Idx, Ts...>;
359 };
360
361 template <size_t Idx, typename... Ts>
362 KOKKOS_INLINE_FUNCTION auto& get(::ippl::Tuple<Ts...>& t) {
363 return t.template get<Idx>();
364 }
365 template <size_t Idx, typename... Ts>
366 KOKKOS_INLINE_FUNCTION const auto& get(const ::ippl::Tuple<Ts...>& t) {
367 return t.template get<Idx>();
368 }
369} // namespace std
370#endif
STL namespace.
KOKKOS_INLINE_FUNCTION auto & get(::ippl::Tuple< Ts... > &t)
Definition Tuple.h:362
Definition Archive.h:20
KOKKOS_INLINE_FUNCTION Tuple< Ts... > makeTuple(Ts &&... args)
Function to create a Tuple with specified elements.
Definition Tuple.h:337
typename TupleTypeImpl< Idx, Ts... >::type TupleType
Definition Tuple.h:349
KOKKOS_INLINE_FUNCTION auto & get(Tuple< Ts... > &t)
Accessor function to get an element mutable reference at a specific index from a Tuple.
Definition Tuple.h:314
Implementation details for the Tuple class.
Definition Tuple.h:28
TupleImpl(TupleImpl< i, N, T, R, Ts... > &&t)=default
KOKKOS_INLINE_FUNCTION auto & get() noexcept
Definition Tuple.h:48
TupleImpl(const TupleImpl< i, N, T, R, Ts... > &t)=default
TupleImpl & operator=(const TupleImpl< i, N, T, R, Ts... > &t)=default
KOKKOS_INLINE_FUNCTION TupleImpl(CtorT &&t, CtorR &&r, CtorTs &&... ts)
Definition Tuple.h:86
TupleImpl< i+1, N, R, Ts... > next
Remaining tuple elements: next doesn't have typename T anymore.
Definition Tuple.h:45
TupleImpl & operator=(TupleImpl< i, N, T, R, Ts... > &&t)=default
KOKKOS_INLINE_FUNCTION const auto & get() const noexcept
Definition Tuple.h:57
KOKKOS_INLINE_FUNCTION TupleImpl(T &&t)
Definition Tuple.h:115
KOKKOS_INLINE_FUNCTION auto & get() noexcept
Definition Tuple.h:102
KOKKOS_INLINE_FUNCTION const auto & get() const noexcept
Definition Tuple.h:107
KOKKOS_INLINE_FUNCTION TupleImpl(const T &t)
Definition Tuple.h:113
Generic tuple class with various operations.
Definition Tuple.h:124
KOKKOS_INLINE_FUNCTION void assignToSequence(const Tuple< OtherTs... > &other, const std::index_sequence< Idx... > &)
Definition Tuple.h:162
KOKKOS_INLINE_FUNCTION Tuple & operator=(const Tuple< OtherTs... > &other)
Definition Tuple.h:185
KOKKOS_INLINE_FUNCTION int applySingle(Functor func, const Tuple< OtherTs... > &other)
Definition Tuple.h:142
KOKKOS_INLINE_FUNCTION int assignToSingle(Tuple< OtherTs... > &&other)
Definition Tuple.h:170
KOKKOS_INLINE_FUNCTION Tuple operator/(const Tuple &other) const
Definition Tuple.h:246
Tuple(Tuple< Ts... > &&t)=default
KOKKOS_INLINE_FUNCTION bool operator==(const Tuple< OtherTs... > &other) const
Definition Tuple.h:277
Tuple(const Tuple< Ts... > &t)=default
KOKKOS_INLINE_FUNCTION Tuple operator-(const Tuple &other) const
Definition Tuple.h:236
KOKKOS_INLINE_FUNCTION int assignToSingle(const Tuple< OtherTs... > &other)
Definition Tuple.h:155
KOKKOS_INLINE_FUNCTION Tuple operator*(const Tuple &other) const
Definition Tuple.h:241
KOKKOS_INLINE_FUNCTION void assignToSequence(Tuple< OtherTs... > &&other, const std::index_sequence< Idx... > &)
Definition Tuple.h:177
KOKKOS_INLINE_FUNCTION auto && get() const noexcept
Definition Tuple.h:138
Tuple & operator=(Tuple< Ts... > &&other)=default
KOKKOS_INLINE_FUNCTION bool lexicographicalLess(const Tuple &other) const
Definition Tuple.h:252
KOKKOS_INLINE_FUNCTION Tuple & operator*=(const Tuple &other)
Definition Tuple.h:215
KOKKOS_INLINE_FUNCTION Tuple & operator+=(const Tuple &other)
Definition Tuple.h:199
KOKKOS_INLINE_FUNCTION void applySequence(Functor func, const Tuple< OtherTs... > &other, const std::index_sequence< Idx... > &)
Definition Tuple.h:149
KOKKOS_INLINE_FUNCTION auto && get() noexcept
Definition Tuple.h:133
KOKKOS_INLINE_FUNCTION Tuple operator+(const Tuple &other) const
Definition Tuple.h:231
Tuple()=default
static constexpr std::size_t size
Definition Tuple.h:130
KOKKOS_INLINE_FUNCTION bool operator<(const Tuple< OtherTs... > &other) const
Definition Tuple.h:271
TupleImpl< 0, sizeof...(Ts), Ts... > tupleImpl_m
Definition Tuple.h:126
static constexpr std::size_t dim
Definition Tuple.h:129
KOKKOS_INLINE_FUNCTION bool lexicographicalEquals(const Tuple &other) const
Definition Tuple.h:262
Tuple & operator=(const Tuple< Ts... > &other)=default
KOKKOS_INLINE_FUNCTION Tuple & operator=(Tuple< OtherTs... > &&other)
Definition Tuple.h:193
KOKKOS_INLINE_FUNCTION Tuple & operator/=(const Tuple &other)
Definition Tuple.h:223
KOKKOS_INLINE_FUNCTION Tuple & operator-=(const Tuple &other)
Definition Tuple.h:207
TupleTypeImpl< Idx - 1, Ts... > type
Definition Tuple.h:342
typename ::ippl::TupleType< Idx, Ts... > type
Definition Tuple.h:358