• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Mehdi Goli    Codeplay Software Ltd.
5 // Ralph Potter  Codeplay Software Ltd.
6 // Luke Iwanski  Codeplay Software Ltd.
7 // Contact: <eigen@codeplay.com>
8 //
9 // This Source Code Form is subject to the terms of the Mozilla
10 // Public License v. 2.0. If a copy of the MPL was not distributed
11 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 
13 /*****************************************************************
14  * TensroSyclTuple.h
15  *
16  * \brief:
17  *  Minimal implementation of std::tuple that can be used inside a SYCL kernel.
18  *
19 *****************************************************************/
20 
21 #ifndef UNSUPPORTED_EIGEN_CXX11_SRC_TENSOR_TENSORSYCL_TUPLE_HPP
22 #define UNSUPPORTED_EIGEN_CXX11_SRC_TENSOR_TENSORSYCL_TUPLE_HPP
23 namespace utility {
24 namespace tuple {
25 /// \struct StaticIf
26 /// \brief The StaticIf struct is used to statically choose the type based on the
27 /// condition.
28 template <bool, typename T = void> struct StaticIf;
29 /// \brief specialisation of the \ref StaticIf when the condition is true
30 template <typename T>
31 struct StaticIf<true, T> {
32   typedef T type;
33 };
34 
35 /// \struct Tuple
36 /// \brief is a fixed-size collection of heterogeneous values
37 /// \ztparam Ts...	-	the types of the elements that the tuple stores.
38 /// Empty list is supported.
39 template <class... Ts>
40 struct Tuple {};
41 
42 /// \brief specialisation of the \ref Tuple class when the tuple has at least
43 /// one element.
44 /// \tparam T : the type of the first element in the tuple.
45 /// \tparam Ts... the rest of the elements in the tuple. Ts... can be empty.
46 template <class T, class... Ts>
47 struct Tuple<T, Ts...> {
48   Tuple(T t, Ts... ts) : head(t), tail(ts...) {}
49   T head;
50   Tuple<Ts...> tail;
51 };
52 
53 ///\ struct ElemTypeHolder
54 /// \brief ElemTypeHolder class is used to specify the types of the
55 /// elements inside the tuple
56 /// \tparam size_t the number of elements inside the tuple
57 /// \tparam class the tuple class
58 template <size_t, class>
59 struct ElemTypeHolder;
60 
61 /// \brief specialisation of the \ref ElemTypeHolder class when the number of
62 /// elements inside the tuple is 1
63 template <class T, class... Ts>
64 struct ElemTypeHolder<0, Tuple<T, Ts...> > {
65   typedef T type;
66 };
67 
68 /// \brief specialisation of the \ref ElemTypeHolder class when the number of
69 /// elements inside the tuple is bigger than 1. It recursively calls itself to
70 /// detect the type of each element in the tuple
71 /// \tparam T : the type of the first element in the tuple.
72 /// \tparam Ts... the rest of the elements in the tuple. Ts... can be empty.
73 /// \tparam K is the Kth element in the tuple
74 template <size_t k, class T, class... Ts>
75 struct ElemTypeHolder<k, Tuple<T, Ts...> > {
76   typedef typename ElemTypeHolder<k - 1, Tuple<Ts...> >::type type;
77 };
78 
79 /// get
80 /// \brief Extracts the first element from the tuple.
81 /// K=0 represents the first element of the tuple. The tuple cannot be empty.
82 /// \tparam Ts... are the type of the elements in the tuple.
83 /// \param t is the tuple whose contents to extract
84 /// \return  typename ElemTypeHolder<0, Tuple<Ts...> >::type &>::type
85 
86 #define TERMINATE_CONDS_TUPLE_GET(CVQual) \
87 template <size_t k, class... Ts> \
88 typename StaticIf<k == 0, CVQual typename ElemTypeHolder<0, Tuple<Ts...> >::type &>::type \
89 get(CVQual Tuple<Ts...> &t) { \
90   static_assert(sizeof...(Ts)!=0, "The requseted value is bigger than the size of the tuple"); \
91   return t.head; \
92 }
93 
94 TERMINATE_CONDS_TUPLE_GET(const)
95 TERMINATE_CONDS_TUPLE_GET()
96 #undef TERMINATE_CONDS_TUPLE_GET
97 /// get
98 /// \brief Extracts the Kth element from the tuple.
99 ///\tparam K is an integer value in [0,sizeof...(Types)).
100 /// \tparam T is the (sizeof...(Types) -(K+1)) element in the tuple
101 /// \tparam Ts... are the type of the elements  in the tuple.
102 /// \param t is the tuple whose contents to extract
103 /// \return  typename ElemTypeHolder<K, Tuple<Ts...> >::type &>::type
104 #define RECURSIVE_TUPLE_GET(CVQual) \
105 template <size_t k, class T, class... Ts> \
106 typename StaticIf<k != 0, CVQual typename ElemTypeHolder<k, Tuple<T, Ts...> >::type &>::type \
107 get(CVQual Tuple<T, Ts...> &t) { \
108   return utility::tuple::get<k - 1>(t.tail); \
109 }
110 RECURSIVE_TUPLE_GET(const)
111 RECURSIVE_TUPLE_GET()
112 #undef RECURSIVE_TUPLE_GET
113 
114 /// make_tuple
115 /// \brief Creates a tuple object, deducing the target type from the types of
116 /// arguments.
117 /// \tparam Args the type of the arguments to construct the tuple from
118 /// \param args zero or more arguments to construct the tuple from
119 /// \return Tuple<Args...>
120 template <typename... Args>
121 Tuple<Args...> make_tuple(Args... args) {
122   return Tuple<Args...>(args...);
123 }
124 
125 /// size
126 /// \brief Provides access to the number of elements in a tuple as a
127 /// compile-time constant expression.
128 /// \tparam Args the type of the arguments to construct the tuple from
129 /// \return size_t
130 template <typename... Args>
131 static constexpr size_t size(Tuple<Args...> &) {
132   return sizeof...(Args);
133 }
134 
135 /// \struct IndexList
136 /// \brief Creates a list of index from the elements in the tuple
137 /// \tparam Is... a list of index from [0 to sizeof...(tuple elements))
138 template <size_t... Is>
139 struct IndexList {};
140 
141 /// \struct RangeBuilder
142 /// \brief Collects internal details for generating index ranges [MIN, MAX)
143 /// Declare primary template for index range builder
144 /// \tparam MIN is the starting index in the tuple
145 /// \tparam N represents sizeof..(elemens)- sizeof...(Is)
146 /// \tparam Is... are the list of generated index so far
147 template <size_t MIN, size_t N, size_t... Is>
148 struct RangeBuilder;
149 
150 /// \brief base Step: Specialisation of the \ref RangeBuilder when the
151 /// MIN==MAX. In this case the Is... is [0 to sizeof...(tuple elements))
152 /// \tparam MIN is the starting index of the tuple
153 /// \tparam Is is [0 to sizeof...(tuple elements))
154 template <size_t MIN, size_t... Is>
155 struct RangeBuilder<MIN, MIN, Is...> {
156   typedef IndexList<Is...> type;
157 };
158 
159 /// Induction step: Specialisation of the RangeBuilder class when N!=MIN
160 /// in this case we are recursively subtracting N by one and adding one
161 /// index to Is... list until MIN==N
162 /// \tparam MIN is the starting index in the tuple
163 /// \tparam N represents sizeof..(elemens)- sizeof...(Is)
164 /// \tparam Is... are the list of generated index so far
165 template <size_t MIN, size_t N, size_t... Is>
166 struct RangeBuilder : public RangeBuilder<MIN, N - 1, N - 1, Is...> {};
167 
168 /// \brief IndexRange that returns a [MIN, MAX) index range
169 /// \tparam MIN is the starting index in the tuple
170 /// \tparam MAX is the size of the tuple
171 template <size_t MIN, size_t MAX>
172 struct IndexRange: RangeBuilder<MIN, MAX>::type {};
173 
174 /// append_base
175 /// \brief unpacking the elements of the input tuple t and creating a new tuple
176 /// by adding element a at the end of it.
177 ///\tparam Args... the type of the elements inside the tuple t
178 /// \tparam T the type of the new element going to be added at the end of tuple
179 /// \tparam I... is the list of index from [0 to sizeof...(t))
180 /// \param t the tuple on which we want to append a.
181 /// \param a the new elements going to be added to the tuple
182 /// \return Tuple<Args..., T>
183 template <typename... Args, typename T, size_t... I>
184 Tuple<Args..., T> append_base(Tuple<Args...> t, T a,IndexList<I...>) {
185   return utility::tuple::make_tuple(get<I>(t)..., a);
186 }
187 
188 /// append
189 /// \brief the deduction function for \ref append_base that automatically
190 /// generate the \ref IndexRange
191 ///\tparam Args... the type of the elements inside the tuple t
192 /// \tparam T the type of the new element going to be added at the end of tuple
193 /// \param t the tuple on which we want to append a.
194 /// \param a the new elements going to be added to the tuple
195 /// \return Tuple<Args..., T>
196 template <typename... Args, typename T>
197 Tuple<Args..., T> append(Tuple<Args...> t, T a) {
198   return utility::tuple::append_base(t, a,  IndexRange<0, sizeof...(Args)>());
199 }
200 
201 /// append_base
202 /// \brief This is a specialisation of \ref append_base when we want to
203 /// concatenate
204 /// tuple t2 at the end of the tuple t1. Here we unpack both tuples, generate the
205 /// IndexRange for each of them and create an output tuple T that contains both
206 /// elements of t1 and t2.
207 ///\tparam Args1... the type of the elements inside the tuple t1
208 ///\tparam Args2... the type of the elements inside the tuple t2
209 /// \tparam I1... is the list of index from [0 to sizeof...(t1))
210 /// \tparam I2... is the list of index from [0 to sizeof...(t2))
211 /// \param t1 is the tuple on which we want to append t2.
212 /// \param t2 is the tuple that is going to be added on t1.
213 /// \return Tuple<Args1..., Args2...>
214 template <typename... Args1, typename... Args2, size_t... I1, size_t... I2>
215 Tuple<Args1..., Args2...> append_base(Tuple<Args1...> t1, Tuple<Args2...> t2, IndexList<I1...>, IndexList<I2...>) {
216   return utility::tuple::make_tuple(get<I1>(t1)...,get<I2>(t2)...);
217 }
218 
219 /// append
220 /// \brief deduction function for \ref append_base when we are appending tuple
221 /// t1 by tuple t2. In this case the \ref IndexRange for both tuple are
222 /// automatically generated.
223 ///\tparam Args1... the type of the elements inside the tuple t1
224 ///\tparam Args2... the type of the elements inside the tuple t2
225 /// \param t1 is the tuple on which we want to append t2.
226 /// \param t2 is the tuple that is going to be added on t1.
227 /// \return Tuple<Args1..., Args2...>
228 template <typename... Args1, typename... Args2>
229 Tuple<Args1..., Args2...> append(Tuple<Args1...> t1,Tuple<Args2...> t2) {
230   return utility::tuple::append_base(t1, t2, IndexRange<0, sizeof...(Args1)>(), IndexRange<0, sizeof...(Args2)>());
231 }
232 }  // tuple
233 }  // utility
234 #endif  // UNSUPPORTED_EIGEN_CXX11_SRC_TENSOR_TENSORSYCL_TUPLE_HPP
235