#pragma once #include "Sequence.hpp" #include "functional2.hpp" template struct Array { using Type = Array; static constexpr index_t nSize = NSize; index_t mData[nSize]; template __host__ __device__ constexpr Array(Xs... xs) : mData{static_cast(xs)...} { } __host__ __device__ constexpr index_t GetSize() const { return NSize; } template __host__ __device__ constexpr TData operator[](Number) const { return mData[I]; } __host__ __device__ constexpr TData operator[](index_t i) const { return mData[i]; } template __host__ __device__ TData& operator()(Number) { return mData[I]; } __host__ __device__ TData& operator()(index_t i) { return mData[i]; } template __host__ __device__ constexpr void Set(Number, TData x) { static_assert(I < NSize, "wrong!"); mData[I] = x; } __host__ __device__ constexpr void Set(index_t I, TData x) { mData[I] = x; } struct lambda_PushBack // emulate constexpr lambda { const Array& old_array; Array& new_array; __host__ __device__ constexpr lambda_PushBack(const Array& old_array_, Array& new_array_) : old_array(old_array_), new_array(new_array_) { } template __host__ __device__ constexpr void operator()(Number) const { new_array.Set(Number{}, old_array[I]); } }; __host__ __device__ constexpr auto PushBack(TData x) const { Array new_array; static_for<0, NSize, 1>{}(lambda_PushBack(*this, new_array)); new_array.Set(Number{}, x); return new_array; } }; template __host__ __device__ constexpr auto sequence2array(Sequence) { return Array{Is...}; } template __host__ __device__ constexpr auto make_zero_array() { constexpr auto zero_sequence = typename uniform_sequence_gen::SeqType{}; constexpr auto zero_array = sequence2array(zero_sequence); return zero_array; } template __host__ __device__ constexpr auto reorder_array_given_new2old(const Array& old_array, Sequence /*new2old*/) { static_assert(NSize == sizeof...(IRs), "NSize not consistent"); static_assert(is_valid_sequence_map>::value, "wrong! invalid reorder map"); return Array{old_array.mSize[IRs]...}; } template struct lambda_reorder_array_given_old2new { const Array& old_array; Array& new_array; __host__ __device__ constexpr lambda_reorder_array_given_old2new( const Array& old_array_, Array& new_array_) : old_array(old_array_), new_array(new_array_) { } template __host__ __device__ constexpr void operator()(Number) const { TData old_data = old_array[IOldDim]; constexpr index_t INewDim = MapOld2New::Get(Number{}); new_array.Set(Number{}, old_data); } }; template __host__ __device__ constexpr auto reorder_array_given_old2new(const Array& old_array, Sequence /*old2new*/) { Array new_array; static_assert(NSize == sizeof...(IRs), "NSize not consistent"); static_assert(is_valid_sequence_map>::value, "wrong! invalid reorder map"); static_for<0, NSize, 1>{}( lambda_reorder_array_given_old2new>(old_array, new_array)); return new_array; } template __host__ __device__ constexpr auto extract_array(const Array& old_array, ExtractSeq) { Array new_array; constexpr index_t new_size = ExtractSeq::GetSize(); static_assert(new_size <= NSize, "wrong! too many extract"); static_for<0, new_size, 1>{}([&](auto I) { new_array(I) = old_array[ExtractSeq::Get(I)]; }); return new_array; } template // emulate constepxr lambda for array math struct lambda_array_math { const F& f; const X& x; const Y& y; Z& z; __host__ __device__ constexpr lambda_array_math(const F& f_, const X& x_, const Y& y_, Z& z_) : f(f_), x(x_), y(y_), z(z_) { } template __host__ __device__ constexpr void operator()(Number) const { constexpr auto IDim = Number{}; z.Set(IDim, f(x[IDim], y[IDim])); } }; // Array = Array + Array template __host__ __device__ constexpr auto operator+(Array a, Array b) { Array result; auto f = mod_conv::plus{}; static_for<0, NSize, 1>{}( lambda_array_math( f, a, b, result)); return result; } // Array = Array - Array template __host__ __device__ constexpr auto operator-(Array a, Array b) { Array result; auto f = mod_conv::minus{}; static_for<0, NSize, 1>{}( lambda_array_math( f, a, b, result)); return result; } // Array = Array + Sequence template __host__ __device__ constexpr auto operator+(Array a, Sequence b) { static_assert(sizeof...(Is) == NSize, "wrong! size not the same"); Array result; auto f = mod_conv::plus{}; static_for<0, NSize, 1>{}( lambda_array_math( f, a, b, result)); return result; } // Array = Array - Sequence template __host__ __device__ constexpr auto operator-(Array a, Sequence b) { static_assert(sizeof...(Is) == NSize, "wrong! size not the same"); Array result; auto f = mod_conv::minus{}; static_for<0, NSize, 1>{}( lambda_array_math( f, a, b, result)); return result; } // Array = Array * Sequence template __host__ __device__ constexpr auto operator*(Array a, Sequence b) { static_assert(sizeof...(Is) == NSize, "wrong! size not the same"); Array result; auto f = mod_conv::multiplies{}; static_for<0, NSize, 1>{}( lambda_array_math( f, a, b, result)); return result; } // Array = Sequence - Array template __host__ __device__ constexpr auto operator-(Sequence a, Array b) { static_assert(sizeof...(Is) == NSize, "wrong! size not the same"); Array result; auto f = mod_conv::minus{}; static_for<0, NSize, 1>{}( lambda_array_math( f, a, b, result)); return result; } template __host__ __device__ constexpr TData accumulate_on_array(const Array& a, Reduce f, TData init) { TData result = init; static_assert(NSize > 0, "wrong"); static_for<0, NSize, 1>{}([&](auto I) { result = f(result, a[I]); }); return result; } template __host__ __device__ void print_Array(const char* s, Array a) { constexpr index_t nsize = a.GetSize(); static_assert(nsize > 0 && nsize <= 10, "wrong!"); static_if{}([&](auto) { printf("%s size %u, {%u}\n", s, nsize, a[0]); }); static_if{}([&](auto) { printf("%s size %u, {%u %u}\n", s, nsize, a[0], a[1]); }); static_if{}( [&](auto) { printf("%s size %u, {%u %u %u}\n", s, nsize, a[0], a[1], a[2]); }); static_if{}( [&](auto) { printf("%s size %u, {%u %u %u %u}\n", s, nsize, a[0], a[1], a[2], a[3]); }); static_if{}([&](auto) { printf("%s size %u, {%u %u %u %u %u}\n", s, nsize, a[0], a[1], a[2], a[3], a[4]); }); static_if{}([&](auto) { printf("%s size %u, {%u %u %u %u %u %u}\n", s, nsize, a[0], a[1], a[2], a[3], a[4], a[5]); }); static_if{}([&](auto) { printf("%s size %u, {%u %u %u %u %u %u %u}\n", s, nsize, a[0], a[1], a[2], a[3], a[4], a[5], a[6]); }); static_if{}([&](auto) { printf("%s size %u, {%u %u %u %u %u %u %u %u}\n", s, nsize, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]); }); static_if{}([&](auto) { printf("%s size %u, {%u %u %u %u %u %u %u %u %u}\n", s, nsize, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]); }); static_if{}([&](auto) { printf("%s size %u, {%u %u %u %u %u %u %u %u %u %u}\n", s, nsize, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]); }); }