// 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: // // 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 struct EnableIf {}; /// \brief specialisation of the \ref EnableIf when the condition is true template struct EnableIf { 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 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 struct Tuple { Tuple(T t, Ts... ts) : head(t), tail(ts...) {} T head; Tuple 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 struct ElemTypeHolder; /// \brief specialisation of the \ref ElemTypeHolder class when the number /// elements inside the tuple is 1 template struct ElemTypeHolder<0, Tuple> { 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 struct ElemTypeHolder> { typedef typename ElemTypeHolder>::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>::type &>::type template typename EnableIf>::type &>::type get(Tuple &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>::type &>::type template typename EnableIf>::type &>::type get(Tuple &t) { return get(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>::type &>::type template typename EnableIf>::type &>::type get(const Tuple &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>::type &>::type template typename EnableIf< k != 0, const typename ElemTypeHolder>::type &>::type get(const Tuple &t) { return get(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 template Tuple make_tuple(Args... args) { return Tuple(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 static constexpr size_t size(Tuple &) { 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 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 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 struct RangeBuilder { typedef Index_list 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 struct RangeBuilder : public RangeBuilder {}; /// \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 using Index_range = typename RangeBuilder::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 template Tuple append_impl(utility::tuple::Tuple t, T a, utility::tuple::Index_list) { return utility::tuple::make_tuple(get(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 template Tuple append(Tuple 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 template Tuple append_impl(utility::tuple::Tuple t1, utility::tuple::Tuple t2, utility::tuple::Index_list, utility::tuple::Index_list) { return utility::tuple::make_tuple(utility::tuple::get(t1)..., utility::tuple::get(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 template Tuple append(utility::tuple::Tuple t1, utility::tuple::Tuple 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