Serac  0.1
Serac is an implicit thermal strucural mechanics simulation code.
tuple.hpp
Go to the documentation of this file.
1 // Copyright (c) 2019-2023, Lawrence Livermore National Security, LLC and
2 // other Serac Project Developers. See the top-level LICENSE file for
3 // details.
4 //
5 // SPDX-License-Identifier: (BSD-3-Clause)
6 
12 #pragma once
13 
14 #include <utility>
15 
17 
18 namespace serac {
19 
27 template <typename... T>
28 struct tuple {
29 };
30 
36 template <typename T0>
37 struct tuple<T0> {
38  T0 v0;
39 };
40 
47 template <typename T0, typename T1>
48 struct tuple<T0, T1> {
49  T0 v0;
50  T1 v1;
51 };
52 
60 template <typename T0, typename T1, typename T2>
61 struct tuple<T0, T1, T2> {
62  T0 v0;
63  T1 v1;
64  T2 v2;
65 };
66 
75 template <typename T0, typename T1, typename T2, typename T3>
76 struct tuple<T0, T1, T2, T3> {
77  T0 v0;
78  T1 v1;
79  T2 v2;
80  T3 v3;
81 };
82 
92 template <typename T0, typename T1, typename T2, typename T3, typename T4>
93 struct tuple<T0, T1, T2, T3, T4> {
94  T0 v0;
95  T1 v1;
96  T2 v2;
97  T3 v3;
98  T4 v4;
99 };
100 
111 template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
112 struct tuple<T0, T1, T2, T3, T4, T5> {
113  T0 v0;
114  T1 v1;
115  T2 v2;
116  T3 v3;
117  T4 v4;
118  T5 v5;
119 };
120 
132 template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
133 struct tuple<T0, T1, T2, T3, T4, T5, T6> {
134  T0 v0;
135  T1 v1;
136  T2 v2;
137  T3 v3;
138  T4 v4;
139  T5 v5;
140  T6 v6;
141 };
142 
155 template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
156 struct tuple<T0, T1, T2, T3, T4, T5, T6, T7> {
157  T0 v0;
158  T1 v1;
159  T2 v2;
160  T3 v3;
161  T4 v4;
162  T5 v5;
163  T6 v6;
164  T7 v7;
165 };
166 
171 template <typename... T>
172 tuple(T...) -> tuple<T...>;
173 
179 template <typename... T>
180 SERAC_HOST_DEVICE tuple<T...> make_tuple(const T&... args)
181 {
182  return tuple<T...>{args...};
183 }
184 
185 template <class... Types>
186 struct tuple_size {
187 };
188 
189 template <class... Types>
190 struct tuple_size<serac::tuple<Types...>> : std::integral_constant<std::size_t, sizeof...(Types)> {
191 };
192 
198 template <int i, typename... T>
199 SERAC_HOST_DEVICE constexpr auto& get(tuple<T...>& values)
200 {
201  static_assert(i < sizeof...(T), "");
202  if constexpr (i == 0) {
203  return values.v0;
204  }
205  if constexpr (i == 1) {
206  return values.v1;
207  }
208  if constexpr (i == 2) {
209  return values.v2;
210  }
211  if constexpr (i == 3) {
212  return values.v3;
213  }
214  if constexpr (i == 4) {
215  return values.v4;
216  }
217  if constexpr (i == 5) {
218  return values.v5;
219  }
220  if constexpr (i == 6) {
221  return values.v6;
222  }
223  if constexpr (i == 7) {
224  return values.v7;
225  }
226 }
227 
233 template <int i, typename... T>
234 SERAC_HOST_DEVICE constexpr const auto& get(const tuple<T...>& values)
235 {
236  static_assert(i < sizeof...(T), "");
237  if constexpr (i == 0) {
238  return values.v0;
239  }
240  if constexpr (i == 1) {
241  return values.v1;
242  }
243  if constexpr (i == 2) {
244  return values.v2;
245  }
246  if constexpr (i == 3) {
247  return values.v3;
248  }
249  if constexpr (i == 4) {
250  return values.v4;
251  }
252  if constexpr (i == 5) {
253  return values.v5;
254  }
255  if constexpr (i == 6) {
256  return values.v6;
257  }
258  if constexpr (i == 7) {
259  return values.v7;
260  }
261 }
262 
273 template <int i, typename... T>
274 SERAC_HOST_DEVICE constexpr auto type(const tuple<T...>& values)
275 {
276  static_assert(i < sizeof...(T), "");
277  if constexpr (i == 0) {
278  return values.v0;
279  }
280  if constexpr (i == 1) {
281  return values.v1;
282  }
283  if constexpr (i == 2) {
284  return values.v2;
285  }
286  if constexpr (i == 3) {
287  return values.v3;
288  }
289  if constexpr (i == 4) {
290  return values.v4;
291  }
292  if constexpr (i == 5) {
293  return values.v5;
294  }
295  if constexpr (i == 6) {
296  return values.v6;
297  }
298  if constexpr (i == 7) {
299  return values.v7;
300  }
301 }
302 
313 template <typename... S, typename... T, int... i>
314 SERAC_HOST_DEVICE constexpr auto plus_helper(const tuple<S...>& x, const tuple<T...>& y,
315  std::integer_sequence<int, i...>)
316 {
317  return tuple{get<i>(x) + get<i>(y)...};
318 }
319 
327 template <typename... S, typename... T>
328 SERAC_HOST_DEVICE constexpr auto operator+(const tuple<S...>& x, const tuple<T...>& y)
329 {
330  static_assert(sizeof...(S) == sizeof...(T));
331  return plus_helper(x, y, std::make_integer_sequence<int, static_cast<int>(sizeof...(S))>());
332 }
333 
342 template <typename... T, int... i>
344  std::integer_sequence<int, i...>)
345 {
346  ((get<i>(x) += get<i>(y)), ...);
347 }
348 
355 template <typename... T>
357 {
358  return plus_equals_helper(x, y, std::make_integer_sequence<int, static_cast<int>(sizeof...(T))>());
359 }
360 
369 template <typename... T, int... i>
371  std::integer_sequence<int, i...>)
372 {
373  ((get<i>(x) -= get<i>(y)), ...);
374 }
375 
382 template <typename... T>
384 {
385  return minus_equals_helper(x, y, std::make_integer_sequence<int, static_cast<int>(sizeof...(T))>());
386 }
387 
398 template <typename... S, typename... T, int... i>
399 SERAC_HOST_DEVICE constexpr auto minus_helper(const tuple<S...>& x, const tuple<T...>& y,
400  std::integer_sequence<int, i...>)
401 {
402  return tuple{get<i>(x) - get<i>(y)...};
403 }
404 
412 template <typename... S, typename... T>
413 SERAC_HOST_DEVICE constexpr auto operator-(const tuple<S...>& x, const tuple<T...>& y)
414 {
415  static_assert(sizeof...(S) == sizeof...(T));
416  return minus_helper(x, y, std::make_integer_sequence<int, static_cast<int>(sizeof...(S))>());
417 }
418 
427 template <typename... T, int... i>
428 SERAC_HOST_DEVICE constexpr auto unary_minus_helper(const tuple<T...>& x, std::integer_sequence<int, i...>)
429 {
430  return tuple{-get<i>(x)...};
431 }
432 
438 template <typename... T>
439 SERAC_HOST_DEVICE constexpr auto operator-(const tuple<T...>& x)
440 {
441  return unary_minus_helper(x, std::make_integer_sequence<int, static_cast<int>(sizeof...(T))>());
442 }
443 
454 template <typename... S, typename... T, int... i>
455 SERAC_HOST_DEVICE constexpr auto div_helper(const tuple<S...>& x, const tuple<T...>& y,
456  std::integer_sequence<int, i...>)
457 {
458  return tuple{get<i>(x) / get<i>(y)...};
459 }
460 
468 template <typename... S, typename... T>
469 SERAC_HOST_DEVICE constexpr auto operator/(const tuple<S...>& x, const tuple<T...>& y)
470 {
471  static_assert(sizeof...(S) == sizeof...(T));
472  return div_helper(x, y, std::make_integer_sequence<int, static_cast<int>(sizeof...(S))>());
473 }
474 
484 template <typename... T, int... i>
485 SERAC_HOST_DEVICE constexpr auto div_helper(const double a, const tuple<T...>& x, std::integer_sequence<int, i...>)
486 {
487  return tuple{a / get<i>(x)...};
488 }
489 
499 template <typename... T, int... i>
500 SERAC_HOST_DEVICE constexpr auto div_helper(const tuple<T...>& x, const double a, std::integer_sequence<int, i...>)
501 {
502  return tuple{get<i>(x) / a...};
503 }
504 
511 template <typename... T>
512 SERAC_HOST_DEVICE constexpr auto operator/(const double a, const tuple<T...>& x)
513 {
514  return div_helper(a, x, std::make_integer_sequence<int, static_cast<int>(sizeof...(T))>());
515 }
516 
523 template <typename... T>
524 SERAC_HOST_DEVICE constexpr auto operator/(const tuple<T...>& x, const double a)
525 {
526  return div_helper(x, a, std::make_integer_sequence<int, static_cast<int>(sizeof...(T))>());
527 }
528 
539 template <typename... S, typename... T, int... i>
540 SERAC_HOST_DEVICE constexpr auto mult_helper(const tuple<S...>& x, const tuple<T...>& y,
541  std::integer_sequence<int, i...>)
542 {
543  return tuple{get<i>(x) * get<i>(y)...};
544 }
545 
553 template <typename... S, typename... T>
554 SERAC_HOST_DEVICE constexpr auto operator*(const tuple<S...>& x, const tuple<T...>& y)
555 {
556  static_assert(sizeof...(S) == sizeof...(T));
557  return mult_helper(x, y, std::make_integer_sequence<int, static_cast<int>(sizeof...(S))>());
558 }
559 
569 template <typename... T, int... i>
570 SERAC_HOST_DEVICE constexpr auto mult_helper(const double a, const tuple<T...>& x, std::integer_sequence<int, i...>)
571 {
572  return tuple{a * get<i>(x)...};
573 }
574 
584 template <typename... T, int... i>
585 SERAC_HOST_DEVICE constexpr auto mult_helper(const tuple<T...>& x, const double a, std::integer_sequence<int, i...>)
586 {
587  return tuple{get<i>(x) * a...};
588 }
589 
596 template <typename... T>
597 SERAC_HOST_DEVICE constexpr auto operator*(const double a, const tuple<T...>& x)
598 {
599  return mult_helper(a, x, std::make_integer_sequence<int, static_cast<int>(sizeof...(T))>());
600 }
601 
608 template <typename... T>
609 SERAC_HOST_DEVICE constexpr auto operator*(const tuple<T...>& x, const double a)
610 {
611  return mult_helper(x, a, std::make_integer_sequence<int, static_cast<int>(sizeof...(T))>());
612 }
613 
621 template <typename... T, std::size_t... i>
622 auto& print_helper(std::ostream& out, const serac::tuple<T...>& A, std::integer_sequence<size_t, i...>)
623 {
624  out << "tuple{";
625  (..., (out << (i == 0 ? "" : ", ") << serac::get<i>(A)));
626  out << "}";
627  return out;
628 }
629 
636 template <typename... T>
637 auto& operator<<(std::ostream& out, const serac::tuple<T...>& A)
638 {
639  return print_helper(out, A, std::make_integer_sequence<size_t, sizeof...(T)>());
640 }
641 
652 template <typename lambda, typename... T, int... i>
653 SERAC_HOST_DEVICE auto apply_helper(lambda f, tuple<T...>& args, std::integer_sequence<int, i...>)
654 {
655  return f(get<i>(args)...);
656 }
657 
667 template <typename lambda, typename... T>
668 SERAC_HOST_DEVICE auto apply(lambda f, tuple<T...>& args)
669 {
670  return apply_helper(f, std::move(args), std::make_integer_sequence<int, static_cast<int>(sizeof...(T))>());
671 }
672 
676 template <typename lambda, typename... T, int... i>
677 SERAC_HOST_DEVICE auto apply_helper(lambda f, const tuple<T...>& args, std::integer_sequence<int, i...>)
678 {
679  return f(get<i>(args)...);
680 }
681 
691 template <typename lambda, typename... T>
692 SERAC_HOST_DEVICE auto apply(lambda f, const tuple<T...>& args)
693 {
694  return apply_helper(f, std::move(args), std::make_integer_sequence<int, static_cast<int>(sizeof...(T))>());
695 }
696 
705 template <size_t I, class T>
707 
708 // recursive case
710 template <size_t I, class Head, class... Tail>
711 struct tuple_element<I, tuple<Head, Tail...>> : tuple_element<I - 1, tuple<Tail...>> {
712 };
713 
714 // base case
716 template <class Head, class... Tail>
717 struct tuple_element<0, tuple<Head, Tail...>> {
718  using type = Head;
719 };
720 
724 template <typename T>
725 struct is_tuple : std::false_type {
726 };
727 
729 template <typename... T>
730 struct is_tuple<serac::tuple<T...>> : std::true_type {
731 };
732 
736 template <typename T>
737 struct is_tuple_of_tuples : std::false_type {
738 };
739 
743 template <typename... T>
745  static constexpr bool value = (is_tuple<T>::value && ...);
746 };
747 
748 } // namespace serac
749 
750 #include "serac/numerics/functional/tuple_tensor_dual_functions.hpp"
This file contains the interface used for initializing/terminating any hardware accelerator-related f...
#define SERAC_HOST_DEVICE
Macro that evaluates to __host__ __device__ when compiling with nvcc and does nothing on a host compi...
Definition: accelerator.hpp:38
Accelerator functionality.
Definition: serac.cpp:38
SERAC_HOST_DEVICE auto apply(lambda f, tuple< T... > &args)
a way of passing an n-tuple to a function that expects n separate arguments
Definition: tuple.hpp:668
constexpr SERAC_HOST_DEVICE auto plus_helper(const tuple< S... > &x, const tuple< T... > &y, std::integer_sequence< int, i... >)
A helper function for the + operator of tuples.
Definition: tuple.hpp:314
constexpr SERAC_HOST_DEVICE auto operator*(const dual< gradient_type > &a, double b)
multiplication of a dual number and a non-dual number
Definition: dual.hpp:109
Domain operator-(const Domain &a, const Domain &b)
create a new domain that is the set difference of a and b
Definition: domain.cpp:500
constexpr T & get(variant< T0, T1 > &v)
Returns the variant member of specified type.
Definition: variant.hpp:338
constexpr SERAC_HOST_DEVICE auto operator+(dual< gradient_type > a, double b)
addition of a dual number and a non-dual number
Definition: dual.hpp:60
constexpr SERAC_HOST_DEVICE void plus_equals_helper(tuple< T... > &x, const tuple< T... > &y, std::integer_sequence< int, i... >)
A helper function for the += operator of tuples.
Definition: tuple.hpp:343
auto & print_helper(std::ostream &out, const serac::tuple< T... > &A, std::integer_sequence< size_t, i... >)
helper used to implement printing a tuple of values
Definition: tuple.hpp:622
constexpr SERAC_HOST_DEVICE auto & operator-=(dual< gradient_type > &a, const dual< gradient_type > &b)
compound assignment (-) for dual numbers
Definition: dual.hpp:192
constexpr SERAC_HOST_DEVICE auto unary_minus_helper(const tuple< T... > &x, std::integer_sequence< int, i... >)
A helper function for the - operator of tuples.
Definition: tuple.hpp:428
SERAC_HOST_DEVICE tuple< T... > make_tuple(const T &... args)
helper function for combining a list of values into a tuple
Definition: tuple.hpp:180
constexpr SERAC_HOST_DEVICE void minus_equals_helper(tuple< T... > &x, const tuple< T... > &y, std::integer_sequence< int, i... >)
A helper function for the -= operator of tuples.
Definition: tuple.hpp:370
auto & operator<<(std::ostream &out, dual< T > A)
overload of operator<< for dual to work with std::cout and other std::ostreams
Definition: dual.hpp:405
tuple(T...) -> tuple< T... >
Class template argument deduction rule for tuples.
constexpr SERAC_HOST_DEVICE auto type(const tuple< T... > &values)
a function intended to be used for extracting the ith type from a tuple.
Definition: tuple.hpp:274
SERAC_HOST_DEVICE auto apply_helper(lambda f, tuple< T... > &args, std::integer_sequence< int, i... >)
A helper to apply a lambda to a tuple.
Definition: tuple.hpp:653
constexpr SERAC_HOST_DEVICE auto & operator+=(dual< gradient_type > &a, const dual< gradient_type > &b)
compound assignment (+) for dual numbers
Definition: dual.hpp:183
constexpr SERAC_HOST_DEVICE auto div_helper(const tuple< S... > &x, const tuple< T... > &y, std::integer_sequence< int, i... >)
A helper function for the / operator of tuples.
Definition: tuple.hpp:455
constexpr SERAC_HOST_DEVICE auto minus_helper(const tuple< S... > &x, const tuple< T... > &y, std::integer_sequence< int, i... >)
A helper function for the - operator of tuples.
Definition: tuple.hpp:399
constexpr SERAC_HOST_DEVICE auto mult_helper(const tuple< S... > &x, const tuple< T... > &y, std::integer_sequence< int, i... >)
A helper function for the * operator of tuples.
Definition: tuple.hpp:540
constexpr SERAC_HOST_DEVICE auto operator/(const dual< gradient_type > &a, double b)
division of a dual number by a non-dual number
Definition: dual.hpp:130
Trait for checking if a type if a serac::tuple containing only serac::tuple.
Definition: tuple.hpp:737
Trait for checking if a type is a serac::tuple.
Definition: tuple.hpp:725
T2 v2
The third member of the tuple.
Definition: tuple.hpp:159
T4 v4
The fifth member of the tuple.
Definition: tuple.hpp:161
T7 v7
The eighth member of the tuple.
Definition: tuple.hpp:164
T0 v0
The first member of the tuple.
Definition: tuple.hpp:157
T1 v1
The second member of the tuple.
Definition: tuple.hpp:158
T3 v3
The fourth member of the tuple.
Definition: tuple.hpp:160
T5 v5
The sixth member of the tuple.
Definition: tuple.hpp:162
T6 v6
The seventh member of the tuple.
Definition: tuple.hpp:163
T0 v0
The first member of the tuple.
Definition: tuple.hpp:134
T1 v1
The second member of the tuple.
Definition: tuple.hpp:135
T5 v5
The sixth member of the tuple.
Definition: tuple.hpp:139
T4 v4
The fifth member of the tuple.
Definition: tuple.hpp:138
T2 v2
The third member of the tuple.
Definition: tuple.hpp:136
T6 v6
The seventh member of the tuple.
Definition: tuple.hpp:140
T3 v3
The fourth member of the tuple.
Definition: tuple.hpp:137
T1 v1
The second member of the tuple.
Definition: tuple.hpp:114
T4 v4
The fifth member of the tuple.
Definition: tuple.hpp:117
T0 v0
The first member of the tuple.
Definition: tuple.hpp:113
T2 v2
The third member of the tuple.
Definition: tuple.hpp:115
T3 v3
The fourth member of the tuple.
Definition: tuple.hpp:116
T5 v5
The sixth member of the tuple.
Definition: tuple.hpp:118
T2 v2
The third member of the tuple.
Definition: tuple.hpp:96
T4 v4
The fifth member of the tuple.
Definition: tuple.hpp:98
T1 v1
The second member of the tuple.
Definition: tuple.hpp:95
T3 v3
The fourth member of the tuple.
Definition: tuple.hpp:97
T0 v0
The first member of the tuple.
Definition: tuple.hpp:94
T3 v3
The fourth member of the tuple.
Definition: tuple.hpp:80
T2 v2
The third member of the tuple.
Definition: tuple.hpp:79
T0 v0
The first member of the tuple.
Definition: tuple.hpp:77
T1 v1
The second member of the tuple.
Definition: tuple.hpp:78
T2 v2
The third member of the tuple.
Definition: tuple.hpp:64
T1 v1
The second member of the tuple.
Definition: tuple.hpp:63
T0 v0
The first member of the tuple.
Definition: tuple.hpp:62
T1 v1
The second member of the tuple.
Definition: tuple.hpp:50
T0 v0
The first member of the tuple.
Definition: tuple.hpp:49
T0 v0
The first member of the tuple.
Definition: tuple.hpp:38
Head type
the type at the specified index
Definition: tuple.hpp:718
a struct used to determine the type at index I of a tuple
Definition: tuple.hpp:706
This is a class that mimics most of std::tuple's interface, except that it is usable in CUDA kernels ...
Definition: tuple.hpp:28