From 6f989d921b12f0941915760d8fb972cdba43aaae Mon Sep 17 00:00:00 2001 From: Bernhard Manfred Gruber Date: Tue, 5 Sep 2023 20:26:32 +0200 Subject: [PATCH] Refactor mapIdx and mapIdxPitchBytes --- include/alpaka/idx/MapIdx.hpp | 281 ++++++++-------------------------- 1 file changed, 63 insertions(+), 218 deletions(-) diff --git a/include/alpaka/idx/MapIdx.hpp b/include/alpaka/idx/MapIdx.hpp index b808b73d4656..af0ccea41701 100644 --- a/include/alpaka/idx/MapIdx.hpp +++ b/include/alpaka/idx/MapIdx.hpp @@ -12,237 +12,82 @@ namespace alpaka { - namespace detail - { - //! Maps a linear index to a N dimensional index. - template - struct MapIdx; - //! Maps a N dimensional index to the same N dimensional index. - template - struct MapIdx - { - // \tparam TElem Type of the index values. - // \param idx Idx to be mapped. - // \param extent Spatial size to map the index to. - // \return A N dimensional vector. - ALPAKA_NO_HOST_ACC_WARNING - template - ALPAKA_FN_HOST_ACC static auto mapIdx( - Vec, TElem> const& idx, - [[maybe_unused]] Vec, TElem> const& extent) -> Vec, TElem> - { - return idx; - } - }; - //! Maps a 1 dimensional index to a N dimensional index. - template - struct MapIdx 1u)>> - { - // \tparam TElem Type of the index values. - // \param idx Idx to be mapped. - // \param extent Spatial size to map the index to - // \return A N dimensional vector. - ALPAKA_NO_HOST_ACC_WARNING - template - ALPAKA_FN_HOST_ACC static auto mapIdx( - Vec, TElem> const& idx, - Vec, TElem> const& extent) -> Vec, TElem> - { - auto idxNd = Vec, TElem>::all(0u); - - constexpr std::size_t lastIdx(TidxDimOut - 1u); - - // fast-dim - idxNd[lastIdx] = static_cast(idx[0u] % extent[lastIdx]); - - // in-between - TElem hyperPlanesBefore = extent[lastIdx]; - for(std::size_t r(1u); r < lastIdx; ++r) - { - std::size_t const d = lastIdx - r; - idxNd[d] = static_cast(idx[0u] / hyperPlanesBefore % extent[d]); - hyperPlanesBefore *= extent[d]; - } - - // slow-dim - idxNd[0u] = static_cast(idx[0u] / hyperPlanesBefore); - - return idxNd; - } - }; - //! Maps a 1 dimensional index to a N dimensional index. - template - struct MapIdx<1u, TidxDimIn, std::enable_if_t<(TidxDimIn > 1u)>> - { - // \tparam TElem Type of the index values. - // \param idx Idx to be mapped. - // \param extent Spatial size to map the index to. - // \return A 1 dimensional vector. - ALPAKA_NO_HOST_ACC_WARNING - template - ALPAKA_FN_HOST_ACC static auto mapIdx( - Vec, TElem> const& idx, - Vec, TElem> const& extent) -> Vec, TElem> - { - TElem idx1d(idx[0u]); - for(std::size_t d(1u); d < TidxDimIn; ++d) - { - idx1d = static_cast(idx1d * extent[d] + idx[d]); - } - return {idx1d}; - } - }; - - template - struct MapIdx - { - template - ALPAKA_FN_HOST_ACC static auto mapIdx( - Vec, TElem> const&, - Vec, TElem> const&) -> Vec, TElem> - { - return Vec, TElem>::zeros(); - } - }; - - template - struct MapIdx<0u, TidxDimIn> - { - template - ALPAKA_FN_HOST_ACC static auto mapIdx( - Vec, TElem> const&, - Vec, TElem> const&) -> Vec, TElem> - { - return {}; - } - }; - } // namespace detail - - //! Maps a N dimensional index to a N dimensional position. + //! Maps an N-dimensional index to an N-dimensional position. At least one dimension must always be 1 or zero. //! - //! \tparam TidxDimOut Dimension of the index vector to map to. - //! \tparam TidxDimIn Dimension of the index vector to map from. - //! \tparam TElem Type of the elements of the index vector to map from. + //! \tparam TDimOut Dimension of the index vector to map to. + //! \param in The index vector to map from. + //! \param extent The extents of the input or output space, whichever has more than 1 dimensions. ALPAKA_NO_HOST_ACC_WARNING template< - std::size_t TidxDimOut, - std::size_t TidxDimIn, - std::size_t TidxDimExtents, + std::size_t TDimOut, + std::size_t TDimIn, + std::size_t TDimExtents, typename TElem> - ALPAKA_FN_HOST_ACC auto mapIdx( - Vec, TElem> const& idx, - Vec, TElem> const& extent) -> Vec, TElem> + ALPAKA_FN_HOST_ACC auto mapIdx(Vec, TElem> const& in, Vec, TElem> const& extent) + -> Vec, TElem> { - return detail::MapIdx::mapIdx(idx, extent); - } - - namespace detail - { - //! Maps a linear index to a N dimensional index assuming a buffer without padding. - template - struct MapIdxPitchBytes; - - //! Maps a N dimensional index to the same N dimensional index assuming a buffer without padding. - template - struct MapIdxPitchBytes - { - // \tparam TElem Type of the index values. - // \param idx Idx to be mapped. - // \param pitch Spatial pitch (in elems) to map the index to - // \return N dimensional vector. - ALPAKA_NO_HOST_ACC_WARNING - template - ALPAKA_FN_HOST_ACC static auto mapIdxPitchBytes( - Vec, TElem> const& idx, - [[maybe_unused]] Vec, TElem> const& pitch) -> Vec, TElem> - { - return idx; - } - }; - //! Maps a 1 dimensional index to a N dimensional index assuming a buffer without padding. - template - struct MapIdxPitchBytes 1u)>> + if constexpr(TDimOut == 0 || TDimIn == 0) + return Vec, TElem>::zeros(); + else if constexpr(TDimOut == TDimIn) + return in; + else if constexpr(TDimOut == 1) { - // \tparam TElem Type of the index values. - // \param idx Idx to be mapped. - // \param pitch Spatial pitch (in elems) to map the index to - // \return N dimensional vector. - ALPAKA_NO_HOST_ACC_WARNING - template - ALPAKA_FN_HOST_ACC static auto mapIdxPitchBytes( - Vec, TElem> const& idx, - Vec, TElem> const& pitch) -> Vec, TElem> - { - auto idxNd = Vec, TElem>::zeros(); - - constexpr std::size_t lastIdx = TidxDimOut - 1u; - - TElem tmp = idx[0u]; - for(std::size_t d(0u); d < lastIdx; ++d) - { - idxNd[d] = static_cast(tmp / pitch[d]); - tmp %= pitch[d]; - } - idxNd[lastIdx] = tmp; - - return idxNd; - } - }; - //! Maps a N dimensional index to a 1 dimensional index assuming a buffer without padding. - template - struct MapIdxPitchBytes<1u, TidxDimIn, std::enable_if_t<(TidxDimIn > 1u)>> + TElem out = in[0]; + for(std::size_t d = 1; d < TDimIn; ++d) + out = static_cast(out * extent[d] + in[d]); + return {out}; + } + else if constexpr(TDimIn == 1) { - // \tparam TElem Type of the index values. - // \param idx Idx to be mapped. - // \param pitch Spatial pitch (in elems) to map the index to - // \return A 1 dimensional vector. - ALPAKA_NO_HOST_ACC_WARNING - template - ALPAKA_FN_HOST_ACC static auto mapIdxPitchBytes( - Vec, TElem> const& idx, - Vec, TElem> const& pitch) -> Vec, TElem> + auto flat = in.front(); + Vec, TElem> out; + for(std::size_t d = TDimOut - 1u; d > 0; d--) { - using DimMinusOne = DimInt; - return {idx.back() + (subVecBegin(pitch) * subVecBegin(idx)).sum()}; + out[d] = static_cast(flat % extent[d]); + flat /= extent[d]; } - }; + out.front() = static_cast(flat); + return out; + } + else + static_assert(!sizeof(TElem), "Not implemented"); + } - template - struct MapIdxPitchBytes + //! Maps an N dimensional index to a N dimensional position based on the pitches of a view without padding or a + //! byte view. At least one dimension must always be 1 or zero. + //! + //! \tparam TDimOut Dimension of the index vector to map to. + //! \param in The index vector to map from. + //! \param pitches The pitches of the input or output space, whichever has more than 1 dimensions. + ALPAKA_NO_HOST_ACC_WARNING + template + ALPAKA_FN_HOST_ACC auto mapIdxPitchBytes( + Vec, TElem> const& in, + Vec, TElem> const& pitches) -> Vec, TElem> + { + if constexpr(TDimOut == 0 || TDimIn == 0) + return Vec, TElem>::zeros(); + else if constexpr(TDimOut == TDimIn) + return in; + else if constexpr(TDimOut == 1) { - template - ALPAKA_FN_HOST_ACC static auto mapIdxPitchBytes( - Vec, TElem> const&, - Vec, TElem> const&) -> Vec, TElem> - { - return Vec, TElem>::zeros(); - } - }; - - template - struct MapIdxPitchBytes<0u, TidxDimIn> + using DimMinusOne = DimInt; + return {in.back() + (subVecBegin(pitches) * subVecBegin(in)).sum()}; + } + else if constexpr(TDimIn == 1) { - template - ALPAKA_FN_HOST_ACC static auto mapIdxPitchBytes( - Vec, TElem> const&, - Vec, TElem> const&) -> Vec, TElem> + auto result = Vec, TElem>::zeros(); + + TElem out = in.front(); + for(std::size_t d = 0; d < TDimOut - 1u; ++d) { - return {}; + result[d] = static_cast(out / pitches[d]); + out %= pitches[d]; } - }; - } // namespace detail + result.back() = out; - //! Maps an N dimensional index to a N dimensional position based on - //! pitch in a buffer without padding or a byte buffer. - //! - //! \tparam TidxDimOut Dimension of the index vector to map to. - //! \tparam TidxDimIn Dimension of the index vector to map from. - //! \tparam TElem Type of the elements of the index vector to map from. - ALPAKA_NO_HOST_ACC_WARNING - template - ALPAKA_FN_HOST_ACC auto mapIdxPitchBytes( - Vec, TElem> const& idx, - Vec, TElem> const& pitch) -> Vec, TElem> - { - return detail::MapIdxPitchBytes::mapIdxPitchBytes(idx, pitch); + return result; + } + else + static_assert(!sizeof(TElem), "Not implemented"); } } // namespace alpaka