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