Home | History | Annotate | Download | only in Tensor
      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 (at) 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