23template <
typename... T>
40template <
typename Self,
typename... U>
41struct is_self_arg : std::false_type {};
44template <
typename Self,
typename U>
45struct is_self_arg<Self, U> : std::is_same<Self, std::decay_t<U>> {};
48template <
typename Self,
typename... U>
49using disable_if_self_t = std::enable_if_t<!is_self_arg<Self, U...>::value>;
56template <
size_t I,
typename T>
62 MFEM_HOST_DEVICE
constexpr tuple_leaf() =
default;
65 template <
typename U,
typename = disable_if_self_t<tuple_leaf, U>>
66 MFEM_HOST_DEVICE
constexpr explicit tuple_leaf(U&& v) :
67 value(
std::forward<U>(v)) {}
79template <
typename Indices,
typename... T>
83template <
size_t... I,
typename... T>
84struct tuple_impl<
std::index_sequence<I...>, T...> : tuple_leaf<I, T>...
87 MFEM_HOST_DEVICE
constexpr tuple_impl() =
default;
97 template <
typename... U,
typename = disable_if_self_t<tuple_impl, U...>>
99 constexpr explicit tuple_impl(U&&... args)
100 : tuple_leaf<I, T>(
std::forward<U>(args))... {}
110template <
bool Viable,
typename Tuple,
typename... U>
111struct is_constructible_from : std::false_type {};
114template <
typename... T,
typename... U>
115struct is_constructible_from<true,
tuple<T...>, U...>
116: std::bool_constant<(std::is_constructible_v<T, U&&> && ...)> {};
124template <
typename Tuple,
typename... U>
125struct is_elementwise_constructible : std::false_type {};
128template <
typename... T,
typename... U>
129struct is_elementwise_constructible<
tuple<T...>, U...>
130 : is_constructible_from<sizeof...(U) == sizeof...(T) && sizeof...(U) != 0 &&
131 !is_self_arg<tuple<T...>, U...>::value, tuple<T...>, U...> {};
134template <
typename Tuple,
typename... U>
135using enable_elementwise_t =
136 std::enable_if_t<is_elementwise_constructible<Tuple, U...>::value>;
148template <
typename... T>
149struct tuple : detail::tuple_impl<std::index_sequence_for<T...>, T...>
151 using base_type = detail::tuple_impl<std::index_sequence_for<T...>, T...>;
166 template <
typename... U,
167 typename = detail::enable_elementwise_t<
tuple, U...>>
195 MFEM_HOST_DEVICE
constexpr tuple() =
default;
202template <
typename... T>
211template <
typename... T>
214 return tuple<T...> {args...};
221template <
class... Types>
224template <
class... Types>
226: std::integral_constant<std::size_t, sizeof...(Types)> {};
236template <
size_t I,
class T>
241template <
size_t I,
class Head,
class... Tail>
247template <
class Head,
class... Tail>
265template <
size_t I,
typename T>
266MFEM_HOST_DEVICE
constexpr T& get_impl(tuple_leaf<I, T>& leaf)
278template <
size_t I,
typename T>
279MFEM_HOST_DEVICE
constexpr const T& get_impl(
const tuple_leaf<I, T>& leaf)
291template <
size_t I,
typename T>
292MFEM_HOST_DEVICE
constexpr T&& get_impl(tuple_leaf<I, T>&& leaf)
294 return static_cast<T&&
>(leaf.value);
304template <
size_t I,
typename T>
305MFEM_HOST_DEVICE
constexpr const T&& get_impl(
const tuple_leaf<I, T>&& leaf)
307 return static_cast<const T&&
>(leaf.value);
317template <
size_t I,
typename... T>
320 static_assert(I <
sizeof...(T),
"Tuple index out of bounds");
321 return detail::get_impl<I>(t);
330template <
size_t I,
typename... T>
333 static_assert(I <
sizeof...(T),
"Tuple index out of bounds");
334 return detail::get_impl<I>(t);
343template <
size_t I,
typename... T>
346 static_assert(I <
sizeof...(T),
"Tuple index out of bounds");
347 return detail::get_impl<I>(std::move(t));
356template <
size_t I,
typename... T>
359 static_assert(I <
sizeof...(T),
"Tuple index out of bounds");
360 return detail::get_impl<I>(std::move(t));
375template <
size_t I,
typename... T>
378 static_assert(I <
sizeof...(T),
"Tuple index out of bounds");
396template <
typename Op,
typename... S,
typename... T,
size_t... I>
397MFEM_HOST_DEVICE
constexpr auto apply_op_helper(
401 std::index_sequence<I...>)
414template <
typename... S,
typename... T>
418 static_assert(
sizeof...(S) ==
sizeof...(T),
"tuples must have same size");
419 return detail::apply_op_helper(x, y,
420 [](
const auto&
a,
const auto&
b) {
return a +
b; },
421 std::make_index_sequence<
sizeof...(S)> {});
431template <
typename... S,
typename... T>
435 static_assert(
sizeof...(S) ==
sizeof...(T),
"tuples must have same size");
436 return detail::apply_op_helper(x, y,
437 [](
const auto&
a,
const auto&
b) {
return a -
b; },
438 std::make_index_sequence<
sizeof...(S)> {});
449template <
typename... S,
typename... T>
453 static_assert(
sizeof...(S) ==
sizeof...(T),
"tuples must have same size");
454 return detail::apply_op_helper(x, y,
455 [](
const auto&
a,
const auto&
b) {
return a *
b; },
456 std::make_index_sequence<
sizeof...(S)> {});
466template <
typename... S,
typename... T>
470 static_assert(
sizeof...(S) ==
sizeof...(T),
"tuples must have same size");
471 return detail::apply_op_helper(x, y,
472 [](
const auto&
a,
const auto&
b) {
return a /
b; },
473 std::make_index_sequence<
sizeof...(S)> {});
486template <
typename... T,
size_t... I>
487MFEM_HOST_DEVICE
constexpr void inplace_add_helper(
490 std::index_sequence<I...>)
502template <
typename... T>
506 detail::inplace_add_helper(x, y, std::make_index_sequence<
sizeof...(T)> {});
520template <
typename... T,
size_t... I>
521MFEM_HOST_DEVICE
constexpr void inplace_sub_helper(
524 std::index_sequence<I...>)
536template <
typename... T>
540 detail::inplace_sub_helper(x, y, std::make_index_sequence<
sizeof...(T)> {});
554template <
typename... T,
size_t... I>
555MFEM_HOST_DEVICE
constexpr auto unary_minus_helper(
557 std::index_sequence<I...>)
569template <
typename... T>
572 return detail::unary_minus_helper(
573 x, std::make_index_sequence<
sizeof...(T)> {});
587template <
typename scalar_t,
typename... T,
size_t... I>
588MFEM_HOST_DEVICE
constexpr auto scalar_mult_helper(
591 std::index_sequence<I...>)
603template <
typename scalar_t,
typename... T>
606 return detail::scalar_mult_helper(
607 a, x, std::make_index_sequence<
sizeof...(T)> {});
616template <
typename scalar_t,
typename... T>
633template <
typename scalar_t,
typename... T,
size_t... I>
634MFEM_HOST_DEVICE
constexpr auto scalar_div_helper(
637 std::index_sequence<I...>)
649template <
typename scalar_t,
typename... T>
652 return detail::scalar_div_helper(
653 x,
a, std::make_index_sequence<
sizeof...(T)> {});
667template <
typename scalar_t,
typename... T,
size_t... I>
668MFEM_HOST_DEVICE
constexpr auto scalar_div_inv_helper(
671 std::index_sequence<I...>)
683template <
typename scalar_t,
typename... T>
686 return detail::scalar_div_inv_helper(
687 a, x, std::make_index_sequence<
sizeof...(T)> {});
699template <
typename... T,
size_t... I>
701 std::index_sequence<I...>)
704 (..., (
out << (I == 0 ?
"" :
", ") <<
get<I>(t)));
716template <
typename... T>
719 return detail::print_helper(
720 out, t, std::make_index_sequence<
sizeof...(T)> {});
735template <
typename F,
typename... T,
size_t... I>
736MFEM_HOST_DEVICE
auto apply_helper(F&&
f,
tuple<T...>& args,
737 std::index_sequence<I...>)
739 return std::forward<F>(
f)(
get<I>(args)...);
753template <
typename F,
typename... T>
756 return detail::apply_helper(std::forward<F>(
f), args,
757 std::make_index_sequence<
sizeof...(T)> {});
765template <
typename F,
typename... T,
size_t... I>
766MFEM_HOST_DEVICE
auto apply_helper(F&&
f,
const tuple<T...>& args,
767 std::index_sequence<I...>)
769 return std::forward<F>(
f)(
get<I>(args)...);
783template <
typename F,
typename... T>
786 return detail::apply_helper(std::forward<F>(
f), args,
787 std::make_index_sequence<
sizeof...(T)> {});
799template <
typename... T>
817template <
typename... T>
827template <
typename... T1s,
typename... T2s>
832 return std::tuple<T1s..., T2s...> {};
844template <
typename... T>
845struct tuple_size<
mfem::future::tuple<T...> >
846: integral_constant<size_t, sizeof...(T)> {};
853template <
size_t I,
typename... T>
854struct tuple_element<I,
mfem::future::tuple<T...>>
MFEM_HOST_DEVICE constexpr auto operator-(dual< value_type, gradient_type > x) -> dual< value_type, gradient_type >
unary negation of a dual number
MFEM_HOST_DEVICE constexpr auto operator+(dual< value_type, gradient_type > a, other_type b) -> dual< value_type, gradient_type >
addition of a dual number and a non-dual number
MFEM_HOST_DEVICE constexpr auto type(const tuple< T... > &t)
a function intended to be used for extracting the ith type from a tuple.
gradient_type MFEM_HOST_DEVICE dual< value_type, gradient_type > & operator+=(dual< value_type, gradient_type > &a, const dual< value_type, gradient_type > &b)
MFEM_HOST_DEVICE auto apply(F &&f, tuple< T... > &args)
a way of passing an n-tuple to a function that expects n separate arguments
MFEM_HOST_DEVICE tuple(T...) -> tuple< T... >
Class template argument deduction rule for tuples.
MFEM_HOST_DEVICE dual< value_type, gradient_type > & operator-=(dual< value_type, gradient_type > &a, const dual< value_type, gradient_type > &b)
compound assignment (-) for dual numbers
MFEM_HOST_DEVICE constexpr tuple< T... > make_tuple(const T &... args)
helper function for combining a list of values into a tuple
std::ostream & operator<<(std::ostream &os, dual< value_type, gradient_type > A)
overload of operator<< for dual to work with work with standard output streams
MFEM_HOST_DEVICE constexpr auto operator*(const dual< value_type, gradient_type > &a, real_t b) -> dual< decltype(a.value *b), decltype(a.gradient *b)>
multiplication of a dual number and a non-dual number
MFEM_HOST_DEVICE constexpr auto operator/(const dual< value_type, gradient_type > &a, real_t b) -> dual< decltype(a.value/b), decltype(a.gradient/b)>
division of a dual number by a non-dual number
MFEM_HOST_DEVICE zero & get(zero &x)
let zero be accessed like a tuple
constexpr auto merge_mfem_tuples_as_empty_std_tuple(const tuple< T1s... > &, const tuple< T2s... > &)
Auxiliary template function that merges (concatenates) two mfem::future::tuple types into a single st...
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Trait for checking if a type if a mfem::tuple containing only mfem::tuple.
Trait for checking if a type is a mfem::tuple.
Specialization for empty tuple.
MFEM_HOST_DEVICE constexpr tuple()=default
Default constructor.
Head type
the type at the specified index
a struct used to determine the type at index I of a tuple
Get the size of a tuple type.
This is a class that mimics most of std::tuple's interface, except that it is usable in CUDA kernels ...
MFEM_HOST_DEVICE constexpr tuple(U &&... args)
Construct tuple from values.
detail::tuple_impl< std::index_sequence_for< T... >, T... > base_type
MFEM_HOST_DEVICE constexpr tuple()=default
Default constructor.
MFEM_HOST_DEVICE constexpr tuple & operator=(const tuple &)=default
Copy assignment operator.
MFEM_HOST_DEVICE constexpr tuple & operator=(tuple &&)=default
Move assignment operator.
MFEM_HOST_DEVICE constexpr tuple(tuple &&)=default
Move constructor.
MFEM_HOST_DEVICE constexpr tuple(const tuple &)=default
Copy constructor.
typename mfem::future::tuple_element< I, mfem::future::tuple< T... > >::type type