Advertisement
JeWe37

Untitled

Nov 23rd, 2017
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.94 KB | None | 0 0
  1. #include <iostream>
  2. #include <utility>
  3. #include <initializer_list>
  4. #include <iterator>
  5. #include <array>
  6. #include <algorithm>
  7. #include <type_traits>
  8. #include <exception>
  9.  
  10. #ifndef UseCores
  11.   #define UseCores 1
  12. #endif
  13.  
  14. namespace linAlgHelper {
  15.   template<typename T> class hasOpSmallerThan {
  16.     template<typename TT> static char test(decltype(&TT::operator<));
  17.     template<typename TT> static long test(...);
  18.   public:
  19.     static const bool value = sizeof(test<T>(0)) == sizeof(char);
  20.   };
  21.  
  22.   template<typename T, typename TT, typename = typename std::enable_if_t<hasOpSmallerThan<T>::value && hasOpSmallerThan<TT>::value>> constexpr inline auto min(T a, TT b) {
  23.     return a < b ? a : b;
  24.   }
  25. }
  26.  
  27. namespace linAlg {
  28.   template<typename T, unsigned ...dims> class Tensor {
  29.   private:
  30.     template<unsigned N, typename TT, unsigned ...dims1> struct Type;
  31.  
  32.     template<unsigned N, unsigned dim, unsigned ...dims1, unsigned ...dims2> struct Type<N, std::integer_sequence<unsigned, dim, dims1...>, dims2...> {
  33.       using type = typename Type<N-1, std::integer_sequence<unsigned, dims1...>, dims2..., dim>::type;
  34.     };
  35.  
  36.     template<unsigned dim, unsigned ...dims1, unsigned ...dims2> struct Type<0, std::integer_sequence<unsigned, dim, dims1...>, dims2...> {
  37.       using type = Tensor<Tensor<T, dim, dims1...>, dims2...>;
  38.     };
  39.  
  40.     template<unsigned N, unsigned dim, unsigned ...dims1> struct getNLowerType {
  41.       using type = typename getNLowerType<N-1, dims1...>::type;
  42.     };
  43.  
  44.     template<unsigned dim, unsigned ...dims1> struct getNLowerType<0, dim, dims1...> {
  45.       using type = Tensor<T, dim, dims1...>;
  46.     };
  47.  
  48.     template<std::size_t N, typename dims1> struct getDim;
  49.  
  50.     template<std::size_t N, unsigned dim, unsigned ...dims1> struct getDim<N, std::integer_sequence<unsigned, dim, dims1...>> {
  51.       static const unsigned value = getDim<N-1, std::integer_sequence<unsigned, dims1...>>::value;
  52.     };
  53.  
  54.     template<std::size_t dim, unsigned ...dims1> struct getDim<0, std::integer_sequence<unsigned, dim, dims1...>> {
  55.       static const unsigned value = dim;
  56.     };
  57.  
  58.     template<typename TT> struct is_Tensor {
  59.       static const bool value = false;
  60.     };
  61.  
  62.     template<typename TT, unsigned ...dims1> struct is_Tensor<Tensor<TT, dims1...>> {
  63.       static const bool value = true;
  64.     };
  65.  
  66.     auto getOneLower() {
  67.       return reinterpret_cast<typename getNLowerType<1, dims...>::type>(scalar.data);
  68.     }
  69.  
  70.     template<typename TT, typename TTT, std::size_t ...idx> static constexpr unsigned minProduct(std::integer_sequence<std::size_t, idx...> int_seq) {
  71.       static_assert(is_Tensor<TT>::value && is_Tensor<TTT>::value, "Can not use minProduct function with type other than linAlg::Tensor.");
  72.       return (linAlgHelper::min(TT::getNthDim<idx>(), TTT::getNthDim<idx>())*...);
  73.     }
  74.   public:
  75.     std::array<T, (dims*...)> scalar;
  76.  
  77.     Tensor() = default;
  78.  
  79.     Tensor(const Tensor<T, dims...>& tensorIn) {
  80.       for (unsigned i = 0; i < (dims*...); i++)
  81.         scalar[i] = tensorIn.scalar[i];
  82.     }
  83.  
  84.     Tensor(Tensor<T, dims...>&& tensorIn) {
  85.       for (unsigned i = 0; i < (dims*...); i++)
  86.         scalar[i] = std::move(tensorIn.scalar[i]);
  87.     }
  88.  
  89.     template<typename ...TT> Tensor(const TT&... args)
  90.     : scalar{args...} {}
  91.  
  92.     Tensor(std::initializer_list<T> list) {
  93.       std::copy(list.begin(), list.end(), std::inserter(scalar, scalar.begin()));
  94.     }
  95.  
  96.     template<typename TT> Tensor(std::initializer_list<std::initializer_list<TT>> list) {
  97.       static_assert(list.size() <= getNthDim<0>());
  98.       auto nextLayer = getOneLower();
  99.       unsigned counter = 0;
  100.       for (std::initializer_list<TT>& list2 : list) {
  101.         nextLayer[counter] = typename getNLowerType<1, dims...>::type(list2);
  102.         ++counter;
  103.       }
  104.     }
  105.  
  106.     template<unsigned dim, unsigned ...dims1> Tensor(const Tensor<T, dim, dims1...>& tensorIn) {
  107.       static_assert(sizeof...(dims1) <= getOrder(), "Can not create Tensor from Tensor of higher order. Use \"getLower()\" instead.");
  108.       for (unsigned i = 0; i < linAlgHelper::min(getNthDim<0>, dim); i++) {
  109.         *reinterpret_cast<Tensor<T, dims1...>*>(scalar.data+i*minProduct<typename getNLowerType<getOrder()-sizeof...(dims1), dims...>::type, Tensor<T, dims1...>>(std::make_index_sequence<sizeof...(dims1)>)) = tensorIn[i];
  110.       }
  111.     }
  112.  
  113.     template<typename TT, unsigned dim, unsigned ...dims1> Tensor(const Tensor<TT, dim, dims1...>& tensorIn) {
  114.       static_assert(is_Tensor<TT>::value && sizeof...(dims1)+TT::getOrder() <= getOrder(), "Can not create Tensor from Tensor of higher order. Use \"getLower()\" instead.");
  115.       static_assert(std::is_same<T, typename TT::type>::value, "Can not use different type for inner Tensor in assignment.");
  116.       for (unsigned i = 0; i < linAlgHelper::min(getNthDim<0>, dim); i++) {
  117.         *reinterpret_cast<Tensor<T, dims1...>*>(scalar.data+i*minProduct<typename getNLowerType<getOrder()-sizeof...(dims1), dims...>::type, Tensor<T, dims1...>>(std::make_index_sequence<sizeof...(dims1)>)) = tensorIn[i];
  118.       }
  119.     }
  120.  
  121.     static constexpr unsigned getOrder() {
  122.       return sizeof...(dims);
  123.     }
  124.  
  125.     template<std::size_t N> static constexpr unsigned getNthDim() {
  126.       return getDim<N, std::integer_sequence<unsigned, dims...>>::value;
  127.     }
  128.  
  129.     template<unsigned dimInt> auto& getLower() {
  130.       return *reinterpret_cast<typename Type<dimInt, std::integer_sequence<unsigned, dims...>>::type*>(this);
  131.     }
  132.  
  133.     auto& operator[] (std::size_t idx) {
  134.       if (idx < getNthDim<0>())
  135.         return getOneLower()[idx];
  136.       throw std::out_of_range("Dimension is lower than index.");
  137.     }
  138.  
  139.     using type = T;
  140.   };
  141.  
  142.   template<typename T, unsigned dim1> using Vector = Tensor<T, dim1>;
  143.   template<typename T, unsigned dim1, unsigned dim2> using Matrix = Tensor<T, dim1, dim2>;
  144. }
  145.  
  146. int main() {
  147.   std::cout << linAlg::Tensor<float, 1, 2, 3, 4, 5, 6, 7, 8>().getLower<5>().scalar.at(0).getOrder() << std::endl;
  148.   return 0;
  149. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement