/*************************************************************************************************** * Copyright (c) 2024 - 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************************************/ #pragma once #include #include #include #include namespace cute { namespace detail { // Empty Structure Optimization template struct ESO; template static constexpr bool is_first_empty_v = cute::is_empty::value; template static constexpr bool is_rest_empty_v = (cute::is_empty::value && ...); template using ESO_t = ESO, is_rest_empty_v, T...>; // Empty First and Empty Rest... template struct ESO { CUTE_HOST_DEVICE constexpr ESO() {} CUTE_HOST_DEVICE constexpr ESO(First const&, Rest const&...) {} }; // NonEmpty First and Empty Rest... template struct ESO { CUTE_HOST_DEVICE constexpr ESO() : first_{} {} CUTE_HOST_DEVICE constexpr ESO(First const& first, Rest const&...) : first_{first} {} First first_; }; // Empty First and NonEmpty Rest... template struct ESO { CUTE_HOST_DEVICE constexpr ESO() : rest_{} {} CUTE_HOST_DEVICE constexpr ESO(First const&, Rest const&... rest) : rest_{rest...} {} ESO_t rest_; }; // NonEmpty T and NonEmpty Rest... template struct ESO { CUTE_HOST_DEVICE constexpr ESO() : first_{}, rest_{} {} CUTE_HOST_DEVICE constexpr ESO(First const& first, Rest const&... rest) : first_{first}, rest_{rest...} {} First first_; ESO_t rest_; }; // Get Nth value from ESO template CUTE_HOST_DEVICE constexpr decltype(auto) getv(ESO const& s) { if constexpr (N == 0) { if constexpr (F) { return T{}; } else { return static_cast(s.first_); } } else { if constexpr (R) { return cute::tuple_element_t>{}; } else { return getv(s.rest_); } } } template CUTE_HOST_DEVICE constexpr decltype(auto) getv(ESO& s) { if constexpr (N == 0) { if constexpr (F) { return T{}; } else { return static_cast(s.first_); } } else { if constexpr (R) { return cute::tuple_element_t>{}; } else { return getv(s.rest_); } } } template CUTE_HOST_DEVICE constexpr decltype(auto) getv(ESO&& s) { if constexpr (N == 0) { if constexpr (F) { return T{}; } else { return static_cast(s.first_); } } else { if constexpr (R) { return cute::tuple_element_t>{}; } else { return getv(static_cast&&>(s.rest_)); } } } // findt: Implementation detail of cute::find. // If X is the first template argument of the tuple, findt returns C. template CUTE_HOST_DEVICE constexpr auto findt(ESO const& t) noexcept { if constexpr (cute::is_same_v) { return C{}; } else { static_assert(sizeof...(Rest) != 0, "The type does not appear in the argument list of the tuple."); if constexpr (IsRestEmpty) { // The rest is empty, so creating an instance of it is cheap. return cute::detail::findt(ESO_t{}); } else { return cute::detail::findt(t.rest_); } } } } // end namespace detail // packed_tuple is a tuple type that is a standard-layout type // whenever all of its template arguments are standard layout types: // (cute::is_standard_layout_v && ...) implies (cute::is_standard_layout_v>) template struct packed_tuple : detail::ESO_t { CUTE_HOST_DEVICE constexpr packed_tuple() {} CUTE_HOST_DEVICE constexpr packed_tuple(T const&... ts) : detail::ESO_t(ts...) {} }; template <> struct packed_tuple<> {}; template CUTE_HOST_DEVICE constexpr decltype(auto) get(packed_tuple const& t) { static_assert(I < sizeof...(T), "Index out of range"); return detail::getv(t); } template CUTE_HOST_DEVICE constexpr decltype(auto) get(packed_tuple& t) { static_assert(I < sizeof...(T), "Index out of range"); return detail::getv(t); } template CUTE_HOST_DEVICE constexpr decltype(auto) get(packed_tuple&& t) { static_assert(I < sizeof...(T), "Index out of range"); return detail::getv(static_cast&&>(t)); } template CUTE_HOST_DEVICE constexpr packed_tuple make_packed_tuple(T const&... t) { return {t...}; } // Returns the position of type X (as a static integer) in the tuple // type's argument list. X must be unique in the argument list. template CUTE_HOST_DEVICE constexpr auto find(packed_tuple const& t) noexcept { return detail::findt(t); } } // end namespace cute namespace CUTE_STL_NAMESPACE { template struct tuple_size> : CUTE_STL_NAMESPACE::integral_constant {}; template struct tuple_element> : CUTE_STL_NAMESPACE::tuple_element> {}; } // end namespace CUTE_STL_NAMESPACE #ifdef CUTE_STL_NAMESPACE_IS_CUDA_STD namespace std { template struct tuple_size> : CUTE_STL_NAMESPACE::integral_constant {}; template struct tuple_element> : CUTE_STL_NAMESPACE::tuple_element> {}; } // end namespace std #endif // CUTE_STL_NAMESPACE_IS_CUDA_STD