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 23namespace utility { 24namespace tuple { 25/// \struct StaticIf 26/// \brief The StaticIf struct is used to statically choose the type based on the 27/// condition. 28template <bool, typename T = void> struct StaticIf; 29/// \brief specialisation of the \ref StaticIf when the condition is true 30template <typename T> 31struct 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. 39template <class... Ts> 40struct 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. 46template <class T, class... Ts> 47struct 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 58template <size_t, class> 59struct ElemTypeHolder; 60 61/// \brief specialisation of the \ref ElemTypeHolder class when the number of 62/// elements inside the tuple is 1 63template <class T, class... Ts> 64struct 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 74template <size_t k, class T, class... Ts> 75struct 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) \ 87template <size_t k, class... Ts> \ 88typename StaticIf<k == 0, CVQual typename ElemTypeHolder<0, Tuple<Ts...> >::type &>::type \ 89get(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 94TERMINATE_CONDS_TUPLE_GET(const) 95TERMINATE_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) \ 105template <size_t k, class T, class... Ts> \ 106typename StaticIf<k != 0, CVQual typename ElemTypeHolder<k, Tuple<T, Ts...> >::type &>::type \ 107get(CVQual Tuple<T, Ts...> &t) { \ 108 return utility::tuple::get<k - 1>(t.tail); \ 109} 110RECURSIVE_TUPLE_GET(const) 111RECURSIVE_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...> 120template <typename... Args> 121Tuple<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 130template <typename... Args> 131static 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)) 138template <size_t... Is> 139struct 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 147template <size_t MIN, size_t N, size_t... Is> 148struct 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)) 154template <size_t MIN, size_t... Is> 155struct 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 165template <size_t MIN, size_t N, size_t... Is> 166struct 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 171template <size_t MIN, size_t MAX> 172struct 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> 183template <typename... Args, typename T, size_t... I> 184Tuple<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> 196template <typename... Args, typename T> 197Tuple<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...> 214template <typename... Args1, typename... Args2, size_t... I1, size_t... I2> 215Tuple<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...> 228template <typename... Args1, typename... Args2> 229Tuple<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