aboutsummaryrefslogtreecommitdiffhomepage
path: root/unsupported/Eigen/CXX11/src/Tensor/TensorSyclTuple.h
blob: 8b9fc52c47131b85ca97ac4675ab50e8fe273ecc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Mehdi Goli    Codeplay Software Ltd.
// Ralph Potter  Codeplay Software Ltd.
// Luke Iwanski  Codeplay Software Ltd.
// Contact: <eigen@codeplay.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

/*****************************************************************
 * TensroSyclTuple.h
 *
 * \brief:
 *  Minimal implementation of std::tuple that can be used inside a SYCL kernel.
 *
*****************************************************************/

#ifndef UNSUPPORTED_EIGEN_CXX11_SRC_TENSORSYCL_TUPLE_HPP
#define UNSUPPORTED_EIGEN_CXX11_SRC_TENSORSYCL_TUPLE_HPP
namespace utility {
namespace tuple {
/// \struct EnableIf
/// \brief The EnableIf struct is used to statically define type based on the
/// condition.
template <bool, typename T = void>
struct EnableIf {};
/// \brief specialisation of the \ref EnableIf when the condition is true
template <typename T>
struct EnableIf<true, T> {
  typedef T type;
};

/// \struct Tuple
/// \brief is a fixed-size collection of heterogeneous values
/// \ztparam Ts... - the types of the elements that the tuple stores.
/// Empty list is supported.
template <class... Ts>
struct Tuple {};

/// \brief specialisation of the \ref Tuple class when the tuple has at least
/// one element.
/// \tparam T : the type of the first element in the tuple.
/// \tparam Ts... the rest of the elements in the tuple. Ts... can be empty.
template <class T, class... Ts>
struct Tuple<T, Ts...> {
  Tuple(T t, Ts... ts) : head(t), tail(ts...) {}

  T head;
  Tuple<Ts...> tail;
};

/// \struct ElemTypeHolder
/// \brief ElemTypeHolder class is used to specify the types of the
/// elements inside the tuple
/// \tparam size_t the number of elements inside the tuple
/// \tparam class the tuple class
template <size_t, class>
struct ElemTypeHolder;

/// \brief specialisation of the \ref ElemTypeHolder class when the number
/// elements inside the tuple is 1
template <class T, class... Ts>
struct ElemTypeHolder<0, Tuple<T, Ts...>> {
  typedef T type;
};

/// \brief specialisation of the \ref ElemTypeHolder class when the number of
/// elements inside the tuple is bigger than 1. It recursively call itself to
/// detect the type of each element in the tuple
/// \tparam T : the type of the first element in the tuple.
/// \tparam Ts... the rest of the elements in the tuple. Ts... can be empty.
/// \tparam K is the Kth element in the tuple
template <size_t k, class T, class... Ts>
struct ElemTypeHolder<k, Tuple<T, Ts...>> {
  typedef typename ElemTypeHolder<k - 1, Tuple<Ts...>>::type type;
};

/// get
/// \brief Extracts the first element from the tuple.
/// K=0 represents the first element of the tuple. The tuple cannot be empty.
/// \tparam Ts... are the elements type in the tuple.
/// \param t is the tuple whose contents to extract
/// \return  typename ElemTypeHolder<0, Tuple<Ts...>>::type &>::type
template <size_t k, class... Ts>
typename EnableIf<k == 0,
                  typename ElemTypeHolder<0, Tuple<Ts...>>::type &>::type
get(Tuple<Ts...> &t) {
  return t.head;
}
/// get
/// \brief Extracts the Kth element from the tuple.
/// \tparam K is an integer value in [0,sizeof...(Types)).
/// \tparam T is the (sizeof...(Types) -(K+1)) element in the tuple
/// \tparam Ts... are the elements type in the tuple.
/// \param t is the tuple whose contents to extract
/// \return  typename ElemTypeHolder<K, Tuple<Ts...>>::type &>::type
template <size_t k, class T, class... Ts>
typename EnableIf<k != 0,
                  typename ElemTypeHolder<k, Tuple<T, Ts...>>::type &>::type
get(Tuple<T, Ts...> &t) {
  return get<k - 1>(t.tail);
}

/// get
/// \brief Extracts the first element from the tuple when the tuple and all the
/// elements inside are const.
/// K=0 represents the first element of the tuple. The tuple cannot be empty.
/// \tparam Ts... are the elements type in the tuple.
/// \param t is the const tuple whose contents to extract
/// \return  const typename ElemTypeHolder<0, Tuple<Ts...>>::type &>::type
template <size_t k, class... Ts>
typename EnableIf<k == 0,
                  const typename ElemTypeHolder<0, Tuple<Ts...>>::type &>::type
get(const Tuple<Ts...> &t) {
  return t.head;
}

/// get
/// \brief Extracts the Kth element from the tuple when the tuple and all the
/// elements inside are const.
/// \tparam K is an integer value in [0,sizeof...(Types)).
/// \tparam T is the (sizeof...(Types) -(K+1)) element in the tuple
/// \tparam Ts... are the elements type in the tuple.
/// \param t is the const tuple whose contents to extract
/// \return  const typename ElemTypeHolder<K, Tuple<Ts...>>::type &>::type
template <size_t k, class T, class... Ts>
typename EnableIf<
    k != 0, const typename ElemTypeHolder<k, Tuple<T, Ts...>>::type &>::type
get(const Tuple<T, Ts...> &t) {
  return get<k - 1>(t.tail);
}
/// make_tuple
/// \brief Creates a tuple object, deducing the target type from the types of
/// arguments.
/// \tparam Args the type of the arguments to construct the tuple from
/// \param args zero or more arguments to construct the tuple from
/// \return Tuple<Args...>
template <typename... Args>
Tuple<Args...> make_tuple(Args... args) {
  return Tuple<Args...>(args...);
}

/// size
/// \brief Provides access to the number of elements in a tuple as a
/// compile-time constant expression.
/// \tparam Args the type of the arguments to construct the tuple from
/// \return size_t
template <typename... Args>
static constexpr size_t size(Tuple<Args...> &) {
  return sizeof...(Args);
}

/// \struct Index_list
/// \brief Creates a list of index from the elements in the tuple
/// \tparam Is... a list of index from [0 to sizeof...(tuple elements))
template <size_t... Is>
struct Index_list {};

/// \struct RangeBuilder
/// \brief Collects internal details for generating index ranges [MIN, MAX)
/// Declare primary template for index range builder
/// \tparam MIN is the starting index in the tuple
/// \tparam N represents sizeof..(elements)- sizeof...(Is)
/// \tparam Is... are the list of generated index so far
template <size_t MIN, size_t N, size_t... Is>
struct RangeBuilder;

/// \brief base Step: Specialisation of the \ref RangeBuilder when the
/// MIN==MAX. In this case the Is... is [0 to sizeof...(tuple elements))
/// \tparam MIN is the starting index of the tuple
/// \tparam Is is [0 to sizeof...(tuple elements))
template <size_t MIN, size_t... Is>
struct RangeBuilder<MIN, MIN, Is...> {
  typedef Index_list<Is...> type;
};

/// Induction step: Specialisation of the RangeBuilder class when N!=MIN
/// in this case we are recursively subtracting the N by one and adding one
/// index to Is... list until MIN==N
/// \tparam MIN is the starting index in the tuple
/// \tparam N represents sizeof..(elements)- sizeof...(Is)
/// \tparam Is... are the list of generated index so far
template <size_t MIN, size_t N, size_t... Is>
struct RangeBuilder : public RangeBuilder<MIN, N - 1, N - 1, Is...> {};

/// \brief IndexRange that returns a [MIN, MAX) index range
/// \tparam MIN is the starting index in the tuple
/// \tparam MAX is the size of the tuple
template <size_t MIN, size_t MAX>
using Index_range = typename RangeBuilder<MIN, MAX>::type;

/// append_impl
/// \brief unpacking the elements of the input tuple t and creating a new tuple
/// by adding element a at the end of it.
/// \tparam Args... the type of the elements inside the tuple t
/// \tparam T the type of the new element going to be added at the end of tuple
/// \tparam I... is the list of index from [0 to sizeof...(t))
/// \param t the tuple on which we want to append a.
/// \param a the new elements going to be added to the tuple
/// \return Tuple<Args..., T>
template <typename... Args, typename T, size_t... I>
Tuple<Args..., T> append_impl(utility::tuple::Tuple<Args...> t, T a,
                              utility::tuple::Index_list<I...>) {
  return utility::tuple::make_tuple(get<I>(t)..., a);
}

/// append
/// \brief the deduction function for \ref append_impl that automatically
/// generate the \ref Index_range
/// \tparam Args... the type of the elements inside the tuple t
/// \tparam T the type of the new element going to be added at the end of tuple
/// \param t the tuple on which we want to append a.
/// \param a the new elements going to be added to the tuple
/// \return Tuple<Args..., T>
template <typename... Args, typename T>
Tuple<Args..., T> append(Tuple<Args...> t, T a) {
  return utility::tuple::append_impl(
      t, a, utility::tuple::Index_range<0, sizeof...(Args)>());
}

/// append_impl
/// \brief This is an specialised of \ref append_impl when we want to
/// concatenate
/// tuple t2 at the end of the tuple t1. Here we unpack both tuples, generate
/// the
/// Index_range for each of them and create an output tuple T that contains both
/// elements of t1 and t2.
/// \tparam Args1... the type of the elements inside the tuple t1
/// \tparam Args2... the type of the elements inside the tuple t2
/// \tparam I1... is the list of index from [0 to sizeof...(t1))
/// \tparam I2... is the list of index from [0 to sizeof...(t2))
/// \param t1 is the tuple on which we want to append t2.
/// \param t2 is the tuple that is going to be added on t1.
/// \return Tuple<Args1..., Args2...>
template <typename... Args1, typename... Args2, size_t... I1, size_t... I2>
Tuple<Args1..., Args2...> append_impl(utility::tuple::Tuple<Args1...> t1,
                                      utility::tuple::Tuple<Args2...> t2,
                                      utility::tuple::Index_list<I1...>,
                                      utility::tuple::Index_list<I2...>) {
  return utility::tuple::make_tuple(utility::tuple::get<I1>(t1)...,
                                    utility::tuple::get<I2>(t2)...);
}
/// append
/// \brief deduction function for \ref append_impl when we are appending tuple
/// t1 by tuple t2. In this case the \ref Index_range for both tuple are
/// automatically generated.
/// \tparam Args1... the type of the elements inside the tuple t1
/// \tparam Args2... the type of the elements inside the tuple t2
/// \param t1 is the tuple on which we want to append t2.
/// \param t2 is the tuple that is going to be added on t1.
/// \return Tuple<Args1..., Args2...>
template <typename... Args1, typename... Args2>
Tuple<Args1..., Args2...> append(utility::tuple::Tuple<Args1...> t1,
                                 utility::tuple::Tuple<Args2...> t2) {
  return utility::tuple::append_impl(
      t1, t2, utility::tuple::Index_range<0, sizeof...(Args1)>(),
      utility::tuple::Index_range<0, sizeof...(Args2)>());
}
}  // tuple
}  // utility
#endif  // UNSUPPORTED_EIGEN_CXX11_SRC_TENSORSYCL_TUPLE_HPP