Tuple.h
Go to the documentation of this file.
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 
10 #ifndef EIGEN_TUPLE_GPU
11 #define EIGEN_TUPLE_GPU
12 
13 #include <type_traits>
14 #include <utility>
15 
16 // This is a replacement of std::tuple that can be used in device code.
17 
18 namespace Eigen {
19 namespace internal {
20 namespace tuple_impl {
21 
22 // Internal tuple implementation.
23 template<size_t N, typename... Types>
24 class TupleImpl;
25 
26 // Generic recursive tuple.
27 template<size_t N, typename T1, typename... Ts>
28 class TupleImpl<N, T1, Ts...> {
29  public:
30  // Tuple may contain Eigen types.
32 
33  // Default constructor, enable if all types are default-constructible.
34  template<typename U1 = T1, typename EnableIf = std::enable_if_t<
35  std::is_default_constructible<U1>::value
36  && reduce_all<std::is_default_constructible<Ts>::value...>::value
37  >>
39  TupleImpl() : head_{}, tail_{} {}
40 
41  // Element constructor.
42  template<typename U1, typename... Us,
43  // Only enable if...
44  typename EnableIf = std::enable_if_t<
45  // the number of input arguments match, and ...
46  sizeof...(Us) == sizeof...(Ts) && (
47  // this does not look like a copy/move constructor.
48  N > 1 || std::is_convertible<U1, T1>::value)
49  >>
51  TupleImpl(U1&& arg1, Us&&... args)
52  : head_(std::forward<U1>(arg1)), tail_(std::forward<Us>(args)...) {}
53 
54  // The first stored value.
56  T1& head() {
57  return head_;
58  }
59 
61  const T1& head() const {
62  return head_;
63  }
64 
65  // The tail values.
67  TupleImpl<N-1, Ts...>& tail() {
68  return tail_;
69  }
70 
72  const TupleImpl<N-1, Ts...>& tail() const {
73  return tail_;
74  }
75 
76  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
77  void swap(TupleImpl& other) {
78  using numext::swap;
79  swap(head_, other.head_);
80  swap(tail_, other.tail_);
81  }
82 
83  template<typename... UTypes>
84  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
85  TupleImpl& operator=(const TupleImpl<N, UTypes...>& other) {
86  head_ = other.head_;
87  tail_ = other.tail_;
88  return *this;
89  }
90 
91  template<typename... UTypes>
92  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
93  TupleImpl& operator=(TupleImpl<N, UTypes...>&& other) {
94  head_ = std::move(other.head_);
95  tail_ = std::move(other.tail_);
96  return *this;
97  }
98 
99  private:
100  // Allow related tuples to reference head_/tail_.
101  template<size_t M, typename... UTypes>
102  friend class TupleImpl;
103 
104  T1 head_;
105  TupleImpl<N-1, Ts...> tail_;
106 };
107 
108 // Empty tuple specialization.
109 template<>
110 class TupleImpl<size_t(0)> {};
111 
112 template<typename TupleType>
113 struct is_tuple : std::false_type {};
114 
115 template<typename... Types>
116 struct is_tuple< TupleImpl<sizeof...(Types), Types...> > : std::true_type {};
117 
118 // Gets an element from a tuple.
119 template<size_t Idx, typename T1, typename... Ts>
120 struct tuple_get_impl {
121  using TupleType = TupleImpl<sizeof...(Ts) + 1, T1, Ts...>;
122  using ReturnType = typename tuple_get_impl<Idx - 1, Ts...>::ReturnType;
123 
125  ReturnType& run(TupleType& tuple) {
126  return tuple_get_impl<Idx-1, Ts...>::run(tuple.tail());
127  }
128 
130  const ReturnType& run(const TupleType& tuple) {
131  return tuple_get_impl<Idx-1, Ts...>::run(tuple.tail());
132  }
133 };
134 
135 // Base case, getting the head element.
136 template<typename T1, typename... Ts>
137 struct tuple_get_impl<0, T1, Ts...> {
138  using TupleType = TupleImpl<sizeof...(Ts) + 1, T1, Ts...>;
139  using ReturnType = T1;
140 
142  T1& run(TupleType& tuple) {
143  return tuple.head();
144  }
145 
147  const T1& run(const TupleType& tuple) {
148  return tuple.head();
149  }
150 };
151 
152 // Concatenates N Tuples.
153 template<size_t NTuples, typename... Tuples>
154 struct tuple_cat_impl;
155 
156 template<size_t NTuples, size_t N1, typename... Args1, size_t N2, typename... Args2, typename... Tuples>
157 struct tuple_cat_impl<NTuples, TupleImpl<N1, Args1...>, TupleImpl<N2, Args2...>, Tuples...> {
158  using TupleType1 = TupleImpl<N1, Args1...>;
159  using TupleType2 = TupleImpl<N2, Args2...>;
160  using MergedTupleType = TupleImpl<N1 + N2, Args1..., Args2...>;
161 
162  using ReturnType = typename tuple_cat_impl<NTuples-1, MergedTupleType, Tuples...>::ReturnType;
163 
164  // Uses the index sequences to extract and merge elements from tuple1 and tuple2,
165  // then recursively calls again.
166  template<typename Tuple1, size_t... I1s, typename Tuple2, size_t... I2s, typename... MoreTuples>
167  static EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
168  ReturnType run(Tuple1&& tuple1, std::index_sequence<I1s...>,
169  Tuple2&& tuple2, std::index_sequence<I2s...>,
170  MoreTuples&&... tuples) {
171  return tuple_cat_impl<NTuples-1, MergedTupleType, Tuples...>::run(
172  MergedTupleType(tuple_get_impl<I1s, Args1...>::run(std::forward<Tuple1>(tuple1))...,
173  tuple_get_impl<I2s, Args2...>::run(std::forward<Tuple2>(tuple2))...),
174  std::forward<MoreTuples>(tuples)...);
175  }
176 
177  // Concatenates the first two tuples.
178  template<typename Tuple1, typename Tuple2, typename... MoreTuples>
179  static EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
180  ReturnType run(Tuple1&& tuple1, Tuple2&& tuple2, MoreTuples&&... tuples) {
181  return run(std::forward<Tuple1>(tuple1), std::make_index_sequence<N1>{},
182  std::forward<Tuple2>(tuple2), std::make_index_sequence<N2>{},
183  std::forward<MoreTuples>(tuples)...);
184  }
185 };
186 
187 // Base case with a single tuple.
188 template<size_t N, typename... Args>
189 struct tuple_cat_impl<1, TupleImpl<N, Args...> > {
190  using ReturnType = TupleImpl<N, Args...>;
191 
192  template<typename Tuple1>
193  static EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
194  ReturnType run(Tuple1&& tuple1) {
195  return tuple1;
196  }
197 };
198 
199 // Special case of no tuples.
200 template<>
201 struct tuple_cat_impl<0> {
202  using ReturnType = TupleImpl<0>;
203  static EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
204  ReturnType run() {return ReturnType{}; }
205 };
206 
207 // For use in make_tuple, unwraps a reference_wrapper.
208 template <typename T>
209 struct unwrap_reference_wrapper { using type = T; };
210 
211 template <typename T>
212 struct unwrap_reference_wrapper<std::reference_wrapper<T> > { using type = T&; };
213 
214 // For use in make_tuple, decays a type and unwraps a reference_wrapper.
215 template <typename T>
216 struct unwrap_decay {
217  using type = typename unwrap_reference_wrapper<typename std::decay<T>::type>::type;
218 };
219 
223 template<typename Tuple>
224 struct tuple_size;
225 
226 template<typename... Types >
227 struct tuple_size< TupleImpl<sizeof...(Types), Types...> > : std::integral_constant<size_t, sizeof...(Types)> {};
228 
236 template<size_t Idx, typename... Types>
237 EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
238 const typename tuple_get_impl<Idx, Types...>::ReturnType&
239 get(const TupleImpl<sizeof...(Types), Types...>& tuple) {
240  return tuple_get_impl<Idx, Types...>::run(tuple);
241 }
242 
243 template<size_t Idx, typename... Types>
244 EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
245 typename tuple_get_impl<Idx, Types...>::ReturnType&
246 get(TupleImpl<sizeof...(Types), Types...>& tuple) {
247  return tuple_get_impl<Idx, Types...>::run(tuple);
248 }
249 
255 template<typename... Tuples,
256  typename EnableIf = std::enable_if_t<
258  is_tuple<typename std::decay<Tuples>::type>::value...>::value>>
259 EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
260 typename tuple_cat_impl<sizeof...(Tuples), typename std::decay<Tuples>::type...>::ReturnType
261 tuple_cat(Tuples&&... tuples) {
262  return tuple_cat_impl<sizeof...(Tuples), typename std::decay<Tuples>::type...>::run(std::forward<Tuples>(tuples)...);
263 }
264 
268 template <typename... Args, typename ReturnType = TupleImpl<sizeof...(Args), Args&...> >
269 EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
270 ReturnType tie(Args&... args) EIGEN_NOEXCEPT {
271  return ReturnType{args...};
272 }
273 
277 template <typename... Args, typename ReturnType = TupleImpl<sizeof...(Args), typename unwrap_decay<Args>::type...> >
278 EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
279 ReturnType make_tuple(Args&&... args) {
280  return ReturnType{std::forward<Args>(args)...};
281 }
282 
286 template <typename... Args>
287 EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
288 TupleImpl<sizeof...(Args), Args...> forward_as_tuple(Args&&... args) {
289  return TupleImpl<sizeof...(Args), Args...>(std::forward<Args>(args)...);
290 }
291 
295 template<typename... Types>
296 using tuple = TupleImpl<sizeof...(Types), Types...>;
297 
298 } // namespace tuple_impl
299 } // namespace internal
300 } // namespace Eigen
301 
302 #endif // EIGEN_TUPLE_GPU
FixedSegmentReturnType<... >::Type head(NType n)
FixedSegmentReturnType<... >::Type tail(NType n)
Matrix4Xd M
#define EIGEN_ALWAYS_INLINE
Definition: Macros.h:836
#define EIGEN_NOEXCEPT
Definition: Macros.h:1260
#define EIGEN_CONSTEXPR
Definition: Macros.h:747
#define EIGEN_DEVICE_FUNC
Definition: Macros.h:883
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Definition: Memory.h:920
Eigen::Triplet< double > T
std::is_same< std::integer_sequence< bool, values..., true >, std::integer_sequence< bool, true, values... > > reduce_all
Definition: Meta.h:296
void swap(scoped_array< T > &a, scoped_array< T > &b)
Definition: Memory.h:788
void swap(T &a, T &b)
Definition: Meta.h:419
: InteropHeaders
Definition: Core:139
Definition: BFloat16.h:222