Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <utility>
- #include <initializer_list>
- #include <iterator>
- #include <array>
- #include <algorithm>
- #include <type_traits>
- #include <exception>
- #ifndef UseCores
- #define UseCores 1
- #endif
- namespace linAlgHelper {
- template<typename T> class hasOpSmallerThan {
- template<typename TT> static char test(decltype(&TT::operator<));
- template<typename TT> static long test(...);
- public:
- static const bool value = sizeof(test<T>(0)) == sizeof(char);
- };
- 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) {
- return a < b ? a : b;
- }
- }
- namespace linAlg {
- template<typename T, unsigned ...dims> class Tensor {
- private:
- template<unsigned N, typename TT, unsigned ...dims1> struct Type;
- template<unsigned N, unsigned dim, unsigned ...dims1, unsigned ...dims2> struct Type<N, std::integer_sequence<unsigned, dim, dims1...>, dims2...> {
- using type = typename Type<N-1, std::integer_sequence<unsigned, dims1...>, dims2..., dim>::type;
- };
- template<unsigned dim, unsigned ...dims1, unsigned ...dims2> struct Type<0, std::integer_sequence<unsigned, dim, dims1...>, dims2...> {
- using type = Tensor<Tensor<T, dim, dims1...>, dims2...>;
- };
- template<unsigned N, unsigned dim, unsigned ...dims1> struct getNLowerType {
- using type = typename getNLowerType<N-1, dims1...>::type;
- };
- template<unsigned dim, unsigned ...dims1> struct getNLowerType<0, dim, dims1...> {
- using type = Tensor<T, dim, dims1...>;
- };
- template<std::size_t N, typename dims1> struct getDim;
- template<std::size_t N, unsigned dim, unsigned ...dims1> struct getDim<N, std::integer_sequence<unsigned, dim, dims1...>> {
- static const unsigned value = getDim<N-1, std::integer_sequence<unsigned, dims1...>>::value;
- };
- template<std::size_t dim, unsigned ...dims1> struct getDim<0, std::integer_sequence<unsigned, dim, dims1...>> {
- static const unsigned value = dim;
- };
- template<typename TT> struct is_Tensor {
- static const bool value = false;
- };
- template<typename TT, unsigned ...dims1> struct is_Tensor<Tensor<TT, dims1...>> {
- static const bool value = true;
- };
- auto getOneLower() {
- return reinterpret_cast<typename getNLowerType<1, dims...>::type>(scalar.data);
- }
- template<typename TT, typename TTT, std::size_t ...idx> static constexpr unsigned minProduct(std::integer_sequence<std::size_t, idx...> int_seq) {
- static_assert(is_Tensor<TT>::value && is_Tensor<TTT>::value, "Can not use minProduct function with type other than linAlg::Tensor.");
- return (linAlgHelper::min(TT::getNthDim<idx>(), TTT::getNthDim<idx>())*...);
- }
- public:
- std::array<T, (dims*...)> scalar;
- Tensor() = default;
- Tensor(const Tensor<T, dims...>& tensorIn) {
- for (unsigned i = 0; i < (dims*...); i++)
- scalar[i] = tensorIn.scalar[i];
- }
- Tensor(Tensor<T, dims...>&& tensorIn) {
- for (unsigned i = 0; i < (dims*...); i++)
- scalar[i] = std::move(tensorIn.scalar[i]);
- }
- template<typename ...TT> Tensor(const TT&... args)
- : scalar{args...} {}
- Tensor(std::initializer_list<T> list) {
- std::copy(list.begin(), list.end(), std::inserter(scalar, scalar.begin()));
- }
- template<typename TT> Tensor(std::initializer_list<std::initializer_list<TT>> list) {
- static_assert(list.size() <= getNthDim<0>());
- auto nextLayer = getOneLower();
- unsigned counter = 0;
- for (std::initializer_list<TT>& list2 : list) {
- nextLayer[counter] = typename getNLowerType<1, dims...>::type(list2);
- ++counter;
- }
- }
- template<unsigned dim, unsigned ...dims1> Tensor(const Tensor<T, dim, dims1...>& tensorIn) {
- static_assert(sizeof...(dims1) <= getOrder(), "Can not create Tensor from Tensor of higher order. Use \"getLower()\" instead.");
- for (unsigned i = 0; i < linAlgHelper::min(getNthDim<0>, dim); i++) {
- *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];
- }
- }
- template<typename TT, unsigned dim, unsigned ...dims1> Tensor(const Tensor<TT, dim, dims1...>& tensorIn) {
- static_assert(is_Tensor<TT>::value && sizeof...(dims1)+TT::getOrder() <= getOrder(), "Can not create Tensor from Tensor of higher order. Use \"getLower()\" instead.");
- static_assert(std::is_same<T, typename TT::type>::value, "Can not use different type for inner Tensor in assignment.");
- for (unsigned i = 0; i < linAlgHelper::min(getNthDim<0>, dim); i++) {
- *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];
- }
- }
- static constexpr unsigned getOrder() {
- return sizeof...(dims);
- }
- template<std::size_t N> static constexpr unsigned getNthDim() {
- return getDim<N, std::integer_sequence<unsigned, dims...>>::value;
- }
- template<unsigned dimInt> auto& getLower() {
- return *reinterpret_cast<typename Type<dimInt, std::integer_sequence<unsigned, dims...>>::type*>(this);
- }
- auto& operator[] (std::size_t idx) {
- if (idx < getNthDim<0>())
- return getOneLower()[idx];
- throw std::out_of_range("Dimension is lower than index.");
- }
- using type = T;
- };
- template<typename T, unsigned dim1> using Vector = Tensor<T, dim1>;
- template<typename T, unsigned dim1, unsigned dim2> using Matrix = Tensor<T, dim1, dim2>;
- }
- int main() {
- std::cout << linAlg::Tensor<float, 1, 2, 3, 4, 5, 6, 7, 8>().getLower<5>().scalar.at(0).getOrder() << std::endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement