#ifndef CK_CONTAINER_ELEMENT_PICKER_HPP #define CK_CONTAINER_ELEMENT_PICKER_HPP #include "functional2.hpp" #include "sequence.hpp" namespace ck { // Arr: Array or StaticallyIndexedArray // Picks: Sequence<...> template struct ContainerElementPicker { using type = ContainerElementPicker; #if 0 using data_type = typename Arr::data_type; #endif __host__ __device__ constexpr ContainerElementPicker() = delete; __host__ __device__ constexpr ContainerElementPicker(Arr& array) : mArray{array} { constexpr index_t imax = reduce_on_sequence(Picks{}, math::maximize{}, Number<0>{}); static_assert(imax < Arr::Size(), "wrong! exceeding # array element"); } __host__ __device__ static constexpr auto Size() { return Picks::Size(); } template __host__ __device__ constexpr const auto& At(Number i) const { static_assert(I < Size(), "wrong!"); constexpr auto IP = Picks{}[i]; return mArray[IP]; } template __host__ __device__ constexpr auto& At(Number i) { static_assert(I < Size(), "wrong!"); constexpr auto IP = Picks{}[i]; return mArray(IP); } template __host__ __device__ constexpr const auto& operator[](Number i) const { return At(i); } template __host__ __device__ constexpr auto& operator()(Number i) { return At(i); } template __host__ __device__ constexpr auto operator=(const T& a) { static_assert(T::Size() == Size(), "wrong! size not the same"); static_for<0, Size(), 1>{}([&](auto i) { operator()(i) = a[i]; }); return *this; } private: Arr& mArray; }; // Arr: Array or StaticallyIndexedArray // Picks: Sequence<...> template struct ConstantContainerElementPicker { using type = ConstantContainerElementPicker; #if 0 using data_type = typename Arr::data_type; #endif __host__ __device__ constexpr ConstantContainerElementPicker() = delete; __host__ __device__ constexpr ConstantContainerElementPicker(const Arr& array) : mArray{array} { constexpr index_t imax = reduce_on_sequence(Picks{}, math::maximize{}, Number<0>{}); static_assert(imax < Arr::Size(), "wrong! exceeding # array element"); } __host__ __device__ static constexpr auto Size() { return Picks::Size(); } template __host__ __device__ constexpr const auto& At(Number i) const { static_assert(I < Size(), "wrong!"); constexpr auto IP = Picks{}[i]; return mArray[IP]; } template __host__ __device__ constexpr const auto& operator[](Number i) const { return At(i); } private: const Arr& mArray; }; template __host__ __device__ constexpr auto operator+=(ContainerElementPicker& y, const X& x) { using Y = ContainerElementPicker; constexpr index_t nsize = Y::Size(); static_assert(nsize == X::Size(), "wrong! size not the same"); static_for<0, nsize, 1>{}([&](auto i) { y(i) += x[i]; }); return y; } template __host__ __device__ constexpr auto operator-=(ContainerElementPicker& y, const X& x) { using Y = ContainerElementPicker; constexpr index_t nsize = Y::Size(); static_assert(nsize == X::Size(), "wrong! size not the same"); static_for<0, nsize, 1>{}([&](auto i) { y(i) -= x[i]; }); return y; } template __host__ __device__ constexpr auto pick_container_element(Arr& a, Picks) { return ContainerElementPicker(a); } template __host__ __device__ constexpr auto pick_container_element(const Arr& a, Picks) { return ConstantContainerElementPicker(a); } } // namespace ck #endif