Eigen  5.0.1
 
Loading...
Searching...
No Matches
Tuple.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2021 The Eigen Team
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_TUPLE_GPU
12#define EIGEN_TUPLE_GPU
13
14#include <type_traits>
15#include <utility>
16
17// This is a replacement of std::tuple that can be used in device code.
18
19namespace Eigen {
20namespace internal {
21namespace tuple_impl {
22
23// Internal tuple implementation.
24template <size_t N, typename... Types>
25class TupleImpl;
26
27// Generic recursive tuple.
28template <size_t N, typename T1, typename... Ts>
29class TupleImpl<N, T1, Ts...> {
30 public:
31 // Tuple may contain Eigen types.
32 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
33
34 // Default constructor, enable if all types are default-constructible.
35 template <typename U1 = T1,
36 typename EnableIf = std::enable_if_t<std::is_default_constructible<U1>::value &&
37 reduce_all<std::is_default_constructible<Ts>::value...>::value>>
38 constexpr EIGEN_DEVICE_FUNC TupleImpl() : m_head{}, m_tail{} {}
39
40 // Element constructor.
41 template <typename U1, typename... Us,
42 // Only enable if...
43 typename EnableIf = std::enable_if_t<
44 // the number of input arguments match, and ...
45 sizeof...(Us) == sizeof...(Ts) && (
46 // this does not look like a copy/move constructor.
47 N > 1 || std::is_convertible<U1, T1>::value)>>
48 constexpr EIGEN_DEVICE_FUNC TupleImpl(U1&& arg1, Us&&... args)
49 : m_head(std::forward<U1>(arg1)), m_tail(std::forward<Us>(args)...) {}
50
51 // The first stored value.
52 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T1& head() { return m_head; }
53
54 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE const T1& head() const { return m_head; }
55
56 // The tail values.
57 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE TupleImpl<N - 1, Ts...>& tail() { return m_tail; }
58
59 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE const TupleImpl<N - 1, Ts...>& tail() const { return m_tail; }
60
61 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(TupleImpl& other) {
62 using numext::swap;
63 swap(m_head, other.m_head);
64 swap(m_tail, other.m_tail);
65 }
66
67 template <typename... UTypes>
68 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TupleImpl& operator=(const TupleImpl<N, UTypes...>& other) {
69 m_head = other.m_head;
70 m_tail = other.m_tail;
71 return *this;
72 }
73
74 template <typename... UTypes>
75 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TupleImpl& operator=(TupleImpl<N, UTypes...>&& other) {
76 m_head = std::move(other.m_head);
77 m_tail = std::move(other.m_tail);
78 return *this;
79 }
80
81 private:
82 // Allow related tuples to reference m_head/m_tail.
83 template <size_t M, typename... UTypes>
84 friend class TupleImpl;
85
86 T1 m_head;
87 TupleImpl<N - 1, Ts...> m_tail;
88};
89
90// Empty tuple specialization.
91template <>
92class TupleImpl<size_t(0)> {};
93
94template <typename TupleType>
95struct is_tuple : std::false_type {};
96
97template <typename... Types>
98struct is_tuple<TupleImpl<sizeof...(Types), Types...>> : std::true_type {};
99
100// Gets an element from a tuple.
101template <size_t Idx, typename T1, typename... Ts>
102struct tuple_get_impl {
103 using TupleType = TupleImpl<sizeof...(Ts) + 1, T1, Ts...>;
104 using ReturnType = typename tuple_get_impl<Idx - 1, Ts...>::ReturnType;
105
106 static constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE ReturnType& run(TupleType& tuple) {
107 return tuple_get_impl<Idx - 1, Ts...>::run(tuple.tail());
108 }
109
110 static constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE const ReturnType& run(const TupleType& tuple) {
111 return tuple_get_impl<Idx - 1, Ts...>::run(tuple.tail());
112 }
113};
114
115// Base case, getting the head element.
116template <typename T1, typename... Ts>
117struct tuple_get_impl<0, T1, Ts...> {
118 using TupleType = TupleImpl<sizeof...(Ts) + 1, T1, Ts...>;
119 using ReturnType = T1;
120
121 static constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T1& run(TupleType& tuple) { return tuple.head(); }
122
123 static constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE const T1& run(const TupleType& tuple) { return tuple.head(); }
124};
125
126// Concatenates N Tuples.
127template <size_t NTuples, typename... Tuples>
128struct tuple_cat_impl;
129
130template <size_t NTuples, size_t N1, typename... Args1, size_t N2, typename... Args2, typename... Tuples>
131struct tuple_cat_impl<NTuples, TupleImpl<N1, Args1...>, TupleImpl<N2, Args2...>, Tuples...> {
132 using TupleType1 = TupleImpl<N1, Args1...>;
133 using TupleType2 = TupleImpl<N2, Args2...>;
134 using MergedTupleType = TupleImpl<N1 + N2, Args1..., Args2...>;
135
136 using ReturnType = typename tuple_cat_impl<NTuples - 1, MergedTupleType, Tuples...>::ReturnType;
137
138 // Uses the index sequences to extract and merge elements from tuple1 and tuple2,
139 // then recursively calls again.
140 template <typename Tuple1, size_t... I1s, typename Tuple2, size_t... I2s, typename... MoreTuples>
141 static constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ReturnType run(Tuple1&& tuple1, std::index_sequence<I1s...>,
142 Tuple2&& tuple2, std::index_sequence<I2s...>,
143 MoreTuples&&... tuples) {
144 return tuple_cat_impl<NTuples - 1, MergedTupleType, Tuples...>::run(
145 MergedTupleType(tuple_get_impl<I1s, Args1...>::run(std::forward<Tuple1>(tuple1))...,
146 tuple_get_impl<I2s, Args2...>::run(std::forward<Tuple2>(tuple2))...),
147 std::forward<MoreTuples>(tuples)...);
148 }
149
150 // Concatenates the first two tuples.
151 template <typename Tuple1, typename Tuple2, typename... MoreTuples>
152 static constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ReturnType run(Tuple1&& tuple1, Tuple2&& tuple2,
153 MoreTuples&&... tuples) {
154 return run(std::forward<Tuple1>(tuple1), std::make_index_sequence<N1>{}, std::forward<Tuple2>(tuple2),
155 std::make_index_sequence<N2>{}, std::forward<MoreTuples>(tuples)...);
156 }
157};
158
159// Base case with a single tuple.
160template <size_t N, typename... Args>
161struct tuple_cat_impl<1, TupleImpl<N, Args...>> {
162 using ReturnType = TupleImpl<N, Args...>;
163
164 template <typename Tuple1>
165 static constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ReturnType run(Tuple1&& tuple1) {
166 return tuple1;
167 }
168};
169
170// Special case of no tuples.
171template <>
172struct tuple_cat_impl<0> {
173 using ReturnType = TupleImpl<0>;
174 static constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ReturnType run() { return ReturnType{}; }
175};
176
177// For use in make_tuple, unwraps a reference_wrapper.
178template <typename T>
179struct unwrap_reference_wrapper {
180 using type = T;
181};
182
183template <typename T>
184struct unwrap_reference_wrapper<std::reference_wrapper<T>> {
185 using type = T&;
186};
187
188// For use in make_tuple, decays a type and unwraps a reference_wrapper.
189template <typename T>
190struct unwrap_decay {
191 using type = typename unwrap_reference_wrapper<std::decay_t<T>>::type;
192};
193
197template <typename Tuple>
199
200template <typename... Types>
201struct tuple_size<TupleImpl<sizeof...(Types), Types...>> : std::integral_constant<size_t, sizeof...(Types)> {};
202
210template <size_t Idx, typename... Types>
211constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename tuple_get_impl<Idx, Types...>::ReturnType& get(
212 const TupleImpl<sizeof...(Types), Types...>& tuple) {
213 return tuple_get_impl<Idx, Types...>::run(tuple);
214}
215
216template <size_t Idx, typename... Types>
217constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename tuple_get_impl<Idx, Types...>::ReturnType& get(
218 TupleImpl<sizeof...(Types), Types...>& tuple) {
219 return tuple_get_impl<Idx, Types...>::run(tuple);
220}
221
227template <typename... Tuples,
228 typename EnableIf = std::enable_if_t<internal::reduce_all<is_tuple<std::decay_t<Tuples>>::value...>::value>>
229constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
230 typename tuple_cat_impl<sizeof...(Tuples), std::decay_t<Tuples>...>::ReturnType
231 tuple_cat(Tuples&&... tuples) {
232 return tuple_cat_impl<sizeof...(Tuples), std::decay_t<Tuples>...>::run(std::forward<Tuples>(tuples)...);
233}
234
238template <typename... Args, typename ReturnType = TupleImpl<sizeof...(Args), Args&...>>
239constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ReturnType tie(Args&... args) noexcept {
240 return ReturnType{args...};
241}
242
246template <typename... Args, typename ReturnType = TupleImpl<sizeof...(Args), typename unwrap_decay<Args>::type...>>
247constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ReturnType make_tuple(Args&&... args) {
248 return ReturnType{std::forward<Args>(args)...};
249}
250
254template <typename... Args>
255constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TupleImpl<sizeof...(Args), Args...> forward_as_tuple(Args&&... args) {
256 return TupleImpl<sizeof...(Args), Args...>(std::forward<Args>(args)...);
257}
258
262template <typename... Types>
263using tuple = TupleImpl<sizeof...(Types), Types...>;
264
265} // namespace tuple_impl
266} // namespace internal
267} // namespace Eigen
268
269#endif // EIGEN_TUPLE_GPU