diff --git a/CMakeLists.txt b/CMakeLists.txt index e75f3c7b..2bd8d6c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,10 +194,10 @@ if(MDSPAN_ENABLE_EXAMPLES) endif() if(MDSPAN_ENABLE_BENCHMARKS) - if(NOT MDSPAN_CXX_STANDARD STREQUAL "14") + if(NOT MDSPAN_CXX_STANDARD STREQUAL "14" AND NOT MDSPAN_CXX_STANDARD STREQUAL "23") add_subdirectory(benchmarks) else() - MESSAGE(FATAL_ERROR "Benchmarks are not available in C++14 mode. Turn MDSPAN_ENABLE_BENCHMARKS OFF or use C++17 or newer.") + MESSAGE(FATAL_ERROR "Benchmarks are not available in C++14 or C++23 mode. Turn MDSPAN_ENABLE_BENCHMARKS OFF or use C++17 or C++20.") endif() endif() diff --git a/compilation_tests/ctest_extents_ctors.cpp b/compilation_tests/ctest_extents_ctors.cpp index cd05b1de..390f6500 100644 --- a/compilation_tests/ctest_extents_ctors.cpp +++ b/compilation_tests/ctest_extents_ctors.cpp @@ -19,6 +19,7 @@ namespace stdex = std::experimental; + MDSPAN_STATIC_TEST( std::is_constructible< stdex::extents, @@ -56,10 +57,11 @@ MDSPAN_STATIC_TEST( >::value ); +// constructibility test from integrals MDSPAN_STATIC_TEST( std::is_constructible< stdex::extents, - int, int, int + int, size_t, int >::value ); @@ -77,6 +79,7 @@ MDSPAN_STATIC_TEST( >::value ); +// conversion construction from extents MDSPAN_STATIC_TEST( std::is_constructible< stdex::extents, @@ -92,35 +95,95 @@ MDSPAN_STATIC_TEST( >::value ); +MDSPAN_STATIC_TEST( + std::is_constructible< + stdex::extents, + stdex::extents + >::value +); + +#if MDSPAN_HAS_CXX_20 +// GNU gets the is_convertible with conditional explicit +// wrong in some older versions. +#if !defined(__GNUC__) || (__GNUC__ > 10) MDSPAN_STATIC_TEST( !std::is_convertible< - stdex::extents, - stdex::extents + stdex::extents, + stdex::extents >::value ); +#endif +#endif MDSPAN_STATIC_TEST( std::is_constructible< - stdex::extents, - stdex::extents + stdex::extents, + stdex::extents + >::value +); + +MDSPAN_STATIC_TEST( + std::is_convertible< + stdex::extents, + stdex::extents + >::value +); + +MDSPAN_STATIC_TEST( + std::is_constructible< + stdex::extents, + stdex::extents + >::value +); + +#if MDSPAN_HAS_CXX_20 +// GNU gets the is_convertible with conditional explicit +// wrong in some older versions. +#if !defined(__GNUC__) || (__GNUC__ > 10) +MDSPAN_STATIC_TEST( + !std::is_convertible< + stdex::extents, + stdex::extents >::value ); +#endif +#endif MDSPAN_STATIC_TEST( std::is_constructible< stdex::extents, - std::array + std::array + >::value +); + +MDSPAN_STATIC_TEST( + std::is_convertible< + std::array, + stdex::extents >::value ); MDSPAN_STATIC_TEST( std::is_constructible< stdex::extents, - std::array + std::array >::value ); +#if MDSPAN_HAS_CXX_20 +// GNU gets the is_convertible with conditional explicit +// wrong in some older versions. +#if !defined(__GNUC__) || (__GNUC__ > 10) +MDSPAN_STATIC_TEST( + !std::is_convertible< + std::array, + stdex::extents + >::value +); +#endif +#endif + MDSPAN_STATIC_TEST( !std::is_constructible< stdex::extents, @@ -136,6 +199,13 @@ MDSPAN_STATIC_TEST( >::value ); +MDSPAN_STATIC_TEST( + std::is_convertible< + std::span, + stdex::extents + >::value +); + MDSPAN_STATIC_TEST( std::is_constructible< stdex::extents, @@ -143,6 +213,19 @@ MDSPAN_STATIC_TEST( >::value ); +#if MDSPAN_HAS_CXX_20 +// GNU gets the is_convertible with conditional explicit +// wrong in some older versions. +#if !defined(__GNUC__) || (__GNUC__ > 10) +MDSPAN_STATIC_TEST( + !std::is_convertible< + std::span, + stdex::extents + >::value +); +#endif +#endif + // this is not supported in the standard MDSPAN_STATIC_TEST( !std::is_constructible< diff --git a/compilation_tests/ctest_no_unique_address.cpp b/compilation_tests/ctest_no_unique_address.cpp index 821e0af0..39db5610 100644 --- a/compilation_tests/ctest_no_unique_address.cpp +++ b/compilation_tests/ctest_no_unique_address.cpp @@ -44,6 +44,7 @@ MDSPAN_STATIC_TEST( sizeof(stdex::extents) == sizeof(ptrdiff_t) ); +#ifdef _MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS MDSPAN_STATIC_TEST( std::is_empty>::value ); @@ -51,6 +52,7 @@ MDSPAN_STATIC_TEST( MDSPAN_STATIC_TEST( std::is_empty>::value ); +#endif // end extents }}}1 //============================================================================== diff --git a/compilation_tests/ctest_standard_layout.cpp b/compilation_tests/ctest_standard_layout.cpp index a4b71cb0..b62daee3 100644 --- a/compilation_tests/ctest_standard_layout.cpp +++ b/compilation_tests/ctest_standard_layout.cpp @@ -21,25 +21,6 @@ namespace stdex = std::experimental; -//============================================================================== -// {{{1 - -MDSPAN_STATIC_TEST( - !std::is_base_of, stdex::detail::__partially_static_sizes>::value -); - -MDSPAN_STATIC_TEST( - !std::is_base_of, stdex::extents>::value -); - -MDSPAN_STATIC_TEST( - std::is_standard_layout< - stdex::detail::__partially_static_sizes - >::value -); - -// end helper utilities }}}1 -//============================================================================== //============================================================================== // {{{1 diff --git a/compilation_tests/ctest_trivially_copyable.cpp b/compilation_tests/ctest_trivially_copyable.cpp index ae602924..3a439d79 100644 --- a/compilation_tests/ctest_trivially_copyable.cpp +++ b/compilation_tests/ctest_trivially_copyable.cpp @@ -21,25 +21,6 @@ namespace stdex = std::experimental; -//============================================================================== -// {{{1 - -MDSPAN_STATIC_TEST( - !std::is_base_of, stdex::detail::__partially_static_sizes>::value -); - -MDSPAN_STATIC_TEST( - !std::is_base_of, stdex::extents>::value -); - -MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - stdex::detail::__partially_static_sizes - >::value -); - -// end helper utilities }}}1 -//============================================================================== //============================================================================== // {{{1 diff --git a/examples/dot_product/dot_product.cpp b/examples/dot_product/dot_product.cpp index 8337bbea..c121ceea 100644 --- a/examples/dot_product/dot_product.cpp +++ b/examples/dot_product/dot_product.cpp @@ -59,7 +59,11 @@ T dot_product( T result = 0; for(int i = 0; i < a.extent(0); ++i) { for(int j = 0; j < a.extent(1); ++j) { +#if MDSPAN_USE_BRACKET_OPERATOR + result += a[i, j] * b[i, j]; +#else result += a(i, j) * b(i, j); +#endif } } return result; @@ -78,7 +82,11 @@ void fill_in_order( T count = 0; for(int i = 0; i < a.extent(0); ++i) { for(int j = 0; j < a.extent(1); ++j) { +#if MDSPAN_USE_BRACKET_OPERATOR + a[i, j] = count++; +#else a(i, j) = count++; +#endif } } } diff --git a/examples/tiled_layout/simple_tiled_layout.cpp b/examples/tiled_layout/simple_tiled_layout.cpp index 3db34c62..bfdcf9b0 100644 --- a/examples/tiled_layout/simple_tiled_layout.cpp +++ b/examples/tiled_layout/simple_tiled_layout.cpp @@ -186,13 +186,23 @@ int main() { int failures = 0; for (int irow = 0; irow < n_rows; ++irow) { for (int icol = 0; icol < n_cols; ++icol) { +#if MDSPAN_USE_BRACKET_OPERATOR + if(tiled[irow, icol] != row_major[irow, icol]) { + std::cout << "Mismatch for entry " << irow << ", " << icol << ":" << std::endl; + std::cout << " tiled(" << irow << ", " << icol << ") = " + << tiled[irow, icol] << std::endl; + std::cout << " row_major(" << irow << ", " << icol << ") = " + << row_major[irow, icol] << std::endl; +#else if(tiled(irow, icol) != row_major(irow, icol)) { std::cout << "Mismatch for entry " << irow << ", " << icol << ":" << std::endl; std::cout << " tiled(" << irow << ", " << icol << ") = " << tiled(irow, icol) << std::endl; std::cout << " row_major(" << irow << ", " << icol << ") = " << row_major(irow, icol) << std::endl; +#endif ++failures; + } } diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index 6969337e..2295d81f 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -13,511 +13,583 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER -#pragma once -#include "macros.hpp" -#include "static_array.hpp" -#include "standard_layout_static_array.hpp" -#include "trait_backports.hpp" // integer_sequence, etc. +#pragma once +#include "dynamic_extent.hpp" -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) -# include "no_unique_address.hpp" +#ifdef __cpp_lib_span +#include #endif - #include -#include + +#include namespace std { namespace experimental { - namespace detail { -template -struct _count_dynamic_extents; - -template -struct _count_dynamic_extents { - static constexpr size_t val = (E==dynamic_extent?1:0) + _count_dynamic_extents::val; -}; - -template<> -struct _count_dynamic_extents<> { - static constexpr size_t val = 0; -}; - +// Function used to check compatibility of extents in converting constructor +// can't be a private member function for some reason. template -static constexpr std::false_type _check_compatible_extents( - std::false_type, std::integer_sequence, std::integer_sequence -) noexcept { return { }; } +static constexpr std::integral_constant __check_compatible_extents( + std::integral_constant, + std::integer_sequence, + std::integer_sequence) noexcept { + return {}; +} // This helper prevents ICE's on MSVC. template -struct _compare_extent_compatible : std::integral_constant +struct __compare_extent_compatible : std::integral_constant {}; template -static std::integral_constant< - bool, - _MDSPAN_FOLD_AND( - ( - _compare_extent_compatible::value - ) /* && ... */ - ) -> -_check_compatible_extents( - std::true_type, std::integer_sequence, std::integer_sequence -) noexcept { return { }; } - -struct __extents_tag { }; +static constexpr std::integral_constant< + bool, _MDSPAN_FOLD_AND(__compare_extent_compatible::value)> +__check_compatible_extents( + std::integral_constant, + std::integer_sequence, + std::integer_sequence) noexcept { + return {}; +} + +// ------------------------------------------------------------------ +// ------------ static_array ---------------------------------------- +// ------------------------------------------------------------------ + +// array like class which provides an array of static values with get +// function and operator []. + +// Implementation of Static Array with recursive implementation of get. +template struct static_array_impl; + +template +struct static_array_impl { + MDSPAN_INLINE_FUNCTION + constexpr static T get(size_t r) { + if (r == R) + return FirstExt; + else + return static_array_impl::get(r); + } + template MDSPAN_INLINE_FUNCTION constexpr static T get() { +#if MDSPAN_HAS_CXX_17 + if constexpr (r == R) + return FirstExt; + else + return static_array_impl::template get(); +#else + get(r); +#endif + } +}; -} // end namespace detail +// End the recursion +template +struct static_array_impl { + MDSPAN_INLINE_FUNCTION + constexpr static T get(size_t) { return FirstExt; } + template MDSPAN_INLINE_FUNCTION constexpr static T get() { + return FirstExt; + } +}; + +// Don't start recursion if size 0 +template struct static_array_impl<0, T> { + MDSPAN_INLINE_FUNCTION + constexpr static T get(size_t) { return T(); } + template MDSPAN_INLINE_FUNCTION constexpr static T get() { + return T(); + } +}; + +// Static array, provides get(), get(r) and operator[r] +template struct static_array: + public static_array_impl<0, T, Values...> { -template -class extents -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : private detail::__no_unique_address_emulation< - detail::__partially_static_sizes_tagged> -#endif -{ public: + using value_type = T; - using rank_type = size_t; - using index_type = ThisIndexType; - static_assert(std::is_integral::value && !std::is_same::value, - "std::extents requires a signed or unsigned integer as index_type parameter"); - using size_type = make_unsigned_t; + MDSPAN_INLINE_FUNCTION + constexpr static size_t size() { return sizeof...(Values); } +}; -// internal typedefs which for technical reasons are public - using __storage_t = detail::__partially_static_sizes_tagged; -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - _MDSPAN_NO_UNIQUE_ADDRESS __storage_t __storage_; -#else - using __base_t = detail::__no_unique_address_emulation<__storage_t>; -#endif +// ------------------------------------------------------------------ +// ------------ index_sequence_scan --------------------------------- +// ------------------------------------------------------------------ -// private members dealing with the way we internally store dynamic extents - private: +// index_sequence_scan takes compile time values and provides get(r) +// and get() which return the sum of the first r-1 values. - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 - __storage_t& __storage() noexcept { -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - return __storage_; -#else - return this->__base_t::__ref(); -#endif +// Recursive implementation for get +template struct index_sequence_scan_impl; + +template +struct index_sequence_scan_impl { + MDSPAN_INLINE_FUNCTION + constexpr static size_t get(size_t r) { + if (r > R) + return FirstVal + index_sequence_scan_impl::get(r); + else + return 0; + } +}; + +template +struct index_sequence_scan_impl { +#if defined(__NVCC__) || defined(__NVCOMPILER) + // NVCC warns about pointless comparison with 0 for R==0 and r being const + // evaluatable and also 0. + MDSPAN_INLINE_FUNCTION + constexpr static size_t get(size_t r) { + return static_cast(R) > static_cast(r) ? FirstVal : 0; } - MDSPAN_FORCE_INLINE_FUNCTION - constexpr __storage_t const& __storage() const noexcept { -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - return __storage_; #else - return this->__base_t::__ref(); + MDSPAN_INLINE_FUNCTION + constexpr static size_t get(size_t r) { return R > r ? FirstVal : 0; } #endif - } +}; +template <> struct index_sequence_scan_impl<0> { + MDSPAN_INLINE_FUNCTION + constexpr static size_t get(size_t) { return 0; } +}; - template - MDSPAN_FORCE_INLINE_FUNCTION - static constexpr - std::size_t _static_extent_impl(size_t n, std::integer_sequence) noexcept { - return _MDSPAN_FOLD_PLUS_RIGHT(((Idxs == n) ? Extents : 0), /* + ... + */ 0); - } +// ------------------------------------------------------------------ +// ------------ possibly_empty_array ------------------------------- +// ------------------------------------------------------------------ - template - friend class extents; +// array like class which provides get function and operator [], and +// has a specialization for the size 0 case. +// This is needed to make the maybe_static_array be truly empty, for +// all static values. - template +template struct possibly_empty_array { + T vals[N]; MDSPAN_INLINE_FUNCTION - constexpr bool _eq_impl(std::experimental::extents, false_type, index_sequence) const noexcept { return false; } - template + constexpr T &operator[](size_t r) { return vals[r]; } MDSPAN_INLINE_FUNCTION - constexpr bool _eq_impl( - std::experimental::extents other, - true_type, index_sequence - ) const noexcept { - return _MDSPAN_FOLD_AND( - (__storage().template __get_n() == other.__storage().template __get_n()) /* && ... */ - ); - } + constexpr const T &operator[](size_t r) const { return vals[r]; } +}; - template +template struct possibly_empty_array { MDSPAN_INLINE_FUNCTION - constexpr bool _not_eq_impl(std::experimental::extents, false_type, index_sequence) const noexcept { return true; } - template + constexpr T operator[](size_t) { return T(); } MDSPAN_INLINE_FUNCTION - constexpr bool _not_eq_impl( - std::experimental::extents other, - true_type, index_sequence - ) const noexcept { - return _MDSPAN_FOLD_OR( - (__storage().template __get_n() != other.__storage().template __get_n()) /* || ... */ - ); - } + constexpr const T operator[](size_t) const { return T(); } +}; -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - MDSPAN_INLINE_FUNCTION constexpr explicit - extents(__base_t&& __b) noexcept - : __base_t(::std::move(__b)) - { } -#endif +// ------------------------------------------------------------------ +// ------------ maybe_static_array ---------------------------------- +// ------------------------------------------------------------------ + +// array like class which has a mix of static and runtime values but +// only stores the runtime values. +// The type of the static and the runtime values can be different. +// The position of a dynamic value is indicated through a tag value. +template +struct maybe_static_array { + + static_assert(is_convertible::value, "maybe_static_array: TStatic must be convertible to TDynamic"); + static_assert(is_convertible::value, "maybe_static_array: TDynamic must be convertible to TStatic"); + +private: + // Static values member + using static_vals_t = static_array; + constexpr static size_t m_size = sizeof...(Values); + constexpr static size_t m_size_dynamic = + _MDSPAN_FOLD_PLUS_RIGHT((Values == dyn_tag), 0); + + // Dynamic values member + _MDSPAN_NO_UNIQUE_ADDRESS possibly_empty_array + m_dyn_vals; + + // static mapping of indices to the position in the dynamic values array + using dyn_map_t = index_sequence_scan_impl<0, static_cast(Values == dyn_tag)...>; +public: + // two types for static and dynamic values + using value_type = TDynamic; + using static_value_type = TStatic; + // tag value indicating dynamic value + constexpr static static_value_type tag_value = dyn_tag; -// public interface: -public: - /* Defined above for use in the private code - using rank_type = size_t; - using index_type = ThisIndexType; - */ + constexpr maybe_static_array() = default; + // constructor for all static values + // TODO: add precondition check? + MDSPAN_TEMPLATE_REQUIRES(class... Vals, + /* requires */ ((m_size_dynamic == 0) && + (sizeof...(Vals) > 0))) MDSPAN_INLINE_FUNCTION - static constexpr rank_type rank() noexcept { return sizeof...(Extents); } - MDSPAN_INLINE_FUNCTION - static constexpr rank_type rank_dynamic() noexcept { return _MDSPAN_FOLD_PLUS_RIGHT((rank_type(Extents == dynamic_extent)), /* + ... + */ 0); } + constexpr maybe_static_array(Vals...) : m_dyn_vals{} {} - //-------------------------------------------------------------------------------- - // Constructors, Destructors, and Assignment + // constructors from dynamic values only + MDSPAN_TEMPLATE_REQUIRES(class... DynVals, + /* requires */ (sizeof...(DynVals) == + m_size_dynamic && + m_size_dynamic > 0)) + MDSPAN_INLINE_FUNCTION + constexpr maybe_static_array(DynVals... vals) + : m_dyn_vals{static_cast(vals)...} {} - // Default constructor - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents() noexcept = default; - // Converting constructor - MDSPAN_TEMPLATE_REQUIRES( - class OtherIndexType, size_t... OtherExtents, - /* requires */ ( - /* multi-stage check to protect from invalid pack expansion when sizes don't match? */ - decltype(detail::_check_compatible_extents( - std::integral_constant{}, - std::integer_sequence{}, - std::integer_sequence{} - ))::value - ) - ) - MDSPAN_INLINE_FUNCTION - MDSPAN_CONDITIONAL_EXPLICIT( - (((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ...) || - (std::numeric_limits::max() < std::numeric_limits::max())) - constexpr extents(const extents& __other) - noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __storage_{ -#else - : __base_t(__base_t{__storage_t{ -#endif - __other.__storage().__enable_psa_conversion() -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#else - }}) -#endif - { - /* TODO: precondition check - * other.extent(r) equals Er for each r for which Er is a static extent, and - * either - * - sizeof...(OtherExtents) is zero, or - * - other.extent(r) is a representable value of type index_type for all rank index r of other - */ + MDSPAN_TEMPLATE_REQUIRES(class T, size_t N, + /* requires */ (N == m_size_dynamic && N > 0)) + MDSPAN_INLINE_FUNCTION + constexpr maybe_static_array(const std::array &vals) { + for (size_t r = 0; r < N; r++) + m_dyn_vals[r] = static_cast(vals[r]); } -#ifdef __NVCC__ - MDSPAN_TEMPLATE_REQUIRES( - class... Integral, - /* requires */ ( - // TODO: check whether the other version works with newest NVCC, doesn't with 11.4 - // NVCC seems to pick up rank_dynamic from the wrong extents type??? - _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_convertible, Integral, index_type) /* && ... */) && - _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_nothrow_constructible, index_type, Integral) /* && ... */) && - // NVCC chokes on the fold thingy here so wrote the workaround - ((sizeof...(Integral) == detail::_count_dynamic_extents::val) || - (sizeof...(Integral) == sizeof...(Extents))) - ) - ) -#else - MDSPAN_TEMPLATE_REQUIRES( - class... Integral, - /* requires */ ( - _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_convertible, Integral, index_type) /* && ... */) && - _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_nothrow_constructible, index_type, Integral) /* && ... */) && - ((sizeof...(Integral) == rank_dynamic()) || (sizeof...(Integral) == rank())) - ) - ) -#endif + MDSPAN_TEMPLATE_REQUIRES(class T, size_t N, + /* requires */ (N == m_size_dynamic && N == 0)) MDSPAN_INLINE_FUNCTION - explicit constexpr extents(Integral... exts) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __storage_{ -#else - : __base_t(__base_t{typename __base_t::__stored_type{ + constexpr maybe_static_array(const std::array &) : m_dyn_vals{} {} + +#ifdef __cpp_lib_span + MDSPAN_TEMPLATE_REQUIRES(class T, size_t N, + /* requires */ (N == m_size_dynamic)) + MDSPAN_INLINE_FUNCTION + constexpr maybe_static_array(const std::span &vals) { + for (size_t r = 0; r < N; r++) + m_dyn_vals[r] = static_cast(vals[r]); + } #endif - std::conditional_t(), - static_cast(exts)... -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) + + // constructors from all values + MDSPAN_TEMPLATE_REQUIRES(class... DynVals, + /* requires */ (sizeof...(DynVals) != + m_size_dynamic && + m_size_dynamic > 0)) + MDSPAN_INLINE_FUNCTION + constexpr maybe_static_array(DynVals... vals) { + static_assert((sizeof...(DynVals) == m_size), "Invalid number of values."); + TDynamic values[m_size]{static_cast(vals)...}; + for (size_t r = 0; r < m_size; r++) { + TStatic static_val = static_vals_t::get(r); + if (static_val == dyn_tag) { + m_dyn_vals[dyn_map_t::get(r)] = values[r]; + } +// Precondition check +#ifdef _MDSPAN_DEBUG + else { + assert(values[r] == static_cast(static_val)); } -#else - }}) #endif - { - /* TODO: precondition check - * If sizeof...(IndexTypes) != rank_dynamic() is true, exts_arr[r] equals Er for each r for which Er is a static extent, and - * either - * - sizeof...(exts) == 0 is true, or - * - each element of exts is nonnegative and is a representable value of type index_type. - */ + } } - // TODO: check whether this works with newest NVCC, doesn't with 11.4 -#ifdef __NVCC__ - // NVCC seems to pick up rank_dynamic from the wrong extents type??? - // NVCC chokes on the fold thingy here so wrote the workaround MDSPAN_TEMPLATE_REQUIRES( - class IndexType, size_t N, - /* requires */ ( - _MDSPAN_TRAIT(is_convertible, IndexType, index_type) && - _MDSPAN_TRAIT(is_nothrow_constructible, index_type, IndexType) && - ((N == detail::_count_dynamic_extents::val) || - (N == sizeof...(Extents))) - ) - ) -#else - MDSPAN_TEMPLATE_REQUIRES( - class IndexType, size_t N, - /* requires */ ( - _MDSPAN_TRAIT(is_convertible, IndexType, index_type) && - _MDSPAN_TRAIT(is_nothrow_constructible, index_type, IndexType) && - (N == rank() || N == rank_dynamic()) - ) - ) -#endif - MDSPAN_CONDITIONAL_EXPLICIT(N != rank_dynamic()) + class T, size_t N, + /* requires */ (N != m_size_dynamic && m_size_dynamic > 0)) MDSPAN_INLINE_FUNCTION - constexpr - extents(std::array const& exts) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __storage_{ -#else - : __base_t(__base_t{typename __base_t::__stored_type{ + constexpr maybe_static_array(const std::array &vals) { + static_assert((N == m_size), "Invalid number of values."); +// Precondition check +#ifdef _MDSPAN_DEBUG + assert(N == m_size); #endif - std::conditional_t, - detail::__construct_psa_from_all_exts_array_tag_t>(), - std::array{exts} -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) + for (size_t r = 0; r < m_size; r++) { + TStatic static_val = static_vals_t::get(r); + if (static_val == dyn_tag) { + m_dyn_vals[dyn_map_t::get(r)] = static_cast(vals[r]); + } +// Precondition check +#ifdef _MDSPAN_DEBUG + else { + assert(static_cast(vals[r]) == + static_cast(static_val)); } -#else - }}) #endif - { - /* TODO: precondition check - * If N != rank_dynamic() is true, exts[r] equals Er for each r for which Er is a static extent, and - * either - * - N is zero, or - * - exts[r] is nonnegative and is a representable value of type index_type for all rank index r - */ + } } #ifdef __cpp_lib_span - // TODO: check whether the below works with newest NVCC, doesn't with 11.4 -#ifdef __NVCC__ - // NVCC seems to pick up rank_dynamic from the wrong extents type??? - // NVCC chokes on the fold thingy here so wrote the workaround MDSPAN_TEMPLATE_REQUIRES( - class IndexType, size_t N, - /* requires */ ( - _MDSPAN_TRAIT(is_convertible, IndexType, index_type) && - _MDSPAN_TRAIT(is_nothrow_constructible, index_type, IndexType) && - ((N == detail::_count_dynamic_extents::val) || - (N == sizeof...(Extents))) - ) - ) -#else - MDSPAN_TEMPLATE_REQUIRES( - class IndexType, size_t N, - /* requires */ ( - _MDSPAN_TRAIT(is_convertible, IndexType, index_type) && - _MDSPAN_TRAIT(is_nothrow_constructible, index_type, IndexType) && - (N == rank() || N == rank_dynamic()) - ) - ) -#endif - MDSPAN_CONDITIONAL_EXPLICIT(N != rank_dynamic()) + class T, size_t N, + /* requires */ (N != m_size_dynamic && m_size_dynamic > 0)) MDSPAN_INLINE_FUNCTION - constexpr - extents(std::span exts) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __storage_{ -#else - : __base_t(__base_t{typename __base_t::__stored_type{ + constexpr maybe_static_array(const std::span &vals) { + static_assert((N == m_size) || (m_size == dynamic_extent)); +#ifdef _MDSPAN_DEBUG + assert(N == m_size); #endif - std::conditional_t, - detail::__construct_psa_from_all_exts_array_tag_t>(), - exts -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) + for (size_t r = 0; r < m_size; r++) { + TStatic static_val = static_vals_t::get(r); + if (static_val == dyn_tag) { + m_dyn_vals[dyn_map_t::get(r)] = static_cast(vals[r]); + } +#ifdef _MDSPAN_DEBUG + else { + assert(static_cast(vals[r]) == + static_cast(static_val)); } -#else - }}) #endif - { - /* TODO: precondition check - * If N != rank_dynamic() is true, exts[r] equals Er for each r for which Er is a static extent, and - * either - * - N is zero, or - * - exts[r] is nonnegative and is a representable value of type index_type for all rank index r - */ + } } #endif - // Need this constructor for some submdspan implementation stuff - // for the layout_stride case where I use an extents object for strides + // access functions MDSPAN_INLINE_FUNCTION - constexpr explicit - extents(__storage_t const& sto ) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __storage_{ -#else - : __base_t(__base_t{ -#endif - sto -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#else - }) -#endif - { } - - //-------------------------------------------------------------------------------- + constexpr static TStatic static_value(size_t r) { return static_vals_t::get(r); } MDSPAN_INLINE_FUNCTION - static constexpr - size_t static_extent(size_t n) noexcept { - // Can't do assert here since that breaks true constexpr ness - // assert(n{}); + constexpr TDynamic value(size_t r) const { + TStatic static_val = static_vals_t::get(r); + return static_val == dyn_tag ? m_dyn_vals[dyn_map_t::get(r)] + : static_cast(static_val); } + MDSPAN_INLINE_FUNCTION + constexpr TDynamic operator[](size_t r) const { return value(r); } + + // observers MDSPAN_INLINE_FUNCTION - constexpr - index_type extent(size_t n) const noexcept { - // Can't do assert here since that breaks true constexpr ness - // assert(n +template class extents { +public: + // typedefs for integral types used + using index_type = IndexType; + using size_type = make_unsigned_t; + using rank_type = size_t; + + static_assert(std::is_integral::value && !std::is_same::value, + "extents::index_type must be a signed or unsigned integer type"); +private: + constexpr static rank_type m_rank = sizeof...(Extents); + constexpr static rank_type m_rank_dynamic = + _MDSPAN_FOLD_PLUS_RIGHT((Extents == dynamic_extent), /* + ... + */ 0); + + // internal storage type using maybe_static_array + using vals_t = + detail::maybe_static_array; + _MDSPAN_NO_UNIQUE_ADDRESS vals_t m_vals; + +public: + // [mdspan.extents.obs], observers of multidimensional index space MDSPAN_INLINE_FUNCTION - friend constexpr bool operator==(extents const& lhs, extents const& rhs) noexcept { - return lhs._eq_impl( - rhs, std::integral_constant{}, - make_index_sequence{} - ); - } + constexpr static rank_type rank() noexcept { return m_rank; } + MDSPAN_INLINE_FUNCTION + constexpr static rank_type rank_dynamic() noexcept { return m_rank_dynamic; } -#if !(MDSPAN_HAS_CXX_20) - template MDSPAN_INLINE_FUNCTION - friend constexpr bool operator!=(extents const& lhs, extents const& rhs) noexcept { - return lhs._not_eq_impl( - rhs, std::integral_constant{}, - make_index_sequence{} - ); + constexpr index_type extent(rank_type r) const noexcept { return m_vals.value(r); } + MDSPAN_INLINE_FUNCTION + constexpr static size_t static_extent(rank_type r) noexcept { + return vals_t::static_value(r); } -#endif - // End of public interface + // [mdspan.extents.cons], constructors + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr extents() noexcept = default; -public: // (but not really) + // Construction from just dynamic or all values. + // Precondition check is deferred to maybe_static_array constructor + MDSPAN_TEMPLATE_REQUIRES( + class... OtherIndexTypes, + /* requires */ ( + _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_convertible, OtherIndexTypes, + index_type) /* && ... */) && + _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_nothrow_constructible, index_type, + OtherIndexTypes) /* && ... */) && + (sizeof...(OtherIndexTypes) == m_rank || + sizeof...(OtherIndexTypes) == m_rank_dynamic))) + MDSPAN_INLINE_FUNCTION + constexpr explicit extents(OtherIndexTypes... dynvals) noexcept + : m_vals(static_cast(dynvals)...) {} - MDSPAN_INLINE_FUNCTION static constexpr - extents __make_extents_impl(detail::__partially_static_sizes&& __bs) noexcept { - // This effectively amounts to a sideways cast that can be done in a constexpr - // context, but we have to do it to handle the case where the extents and the - // strides could accidentally end up with the same types in their hierarchies - // somehow (which would cause layout_stride::mapping to not be standard_layout) - return extents( -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - __base_t{ -#endif - ::std::move(__bs.template __with_tag()) -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } + MDSPAN_TEMPLATE_REQUIRES( + class OtherIndexType, size_t N, + /* requires */ + ( + _MDSPAN_TRAIT(is_convertible, OtherIndexType, index_type) && + _MDSPAN_TRAIT(is_nothrow_constructible, index_type, + OtherIndexType) && + (N == m_rank || N == m_rank_dynamic))) + MDSPAN_INLINE_FUNCTION + MDSPAN_CONDITIONAL_EXPLICIT(N != m_rank_dynamic) + constexpr extents(const array &exts) noexcept + : m_vals(std::move(exts)) {} + +#ifdef __cpp_lib_span + MDSPAN_TEMPLATE_REQUIRES( + class OtherIndexType, size_t N, + /* requires */ + (_MDSPAN_TRAIT(is_convertible, OtherIndexType, index_type) && + _MDSPAN_TRAIT(is_nothrow_constructible, index_type, OtherIndexType) && + (N == m_rank || N == m_rank_dynamic))) + MDSPAN_INLINE_FUNCTION + MDSPAN_CONDITIONAL_EXPLICIT(N != m_rank_dynamic) + constexpr extents(const span &exts) noexcept + : m_vals(std::move(exts)) {} #endif - ); + +private: + // Function to construct extents storage from other extents. + // With C++ 17 the first two variants could be collapsed using if constexpr + // in which case you don't need all the requires clauses. + // in C++ 14 mode that doesn't work due to infinite recursion + MDSPAN_TEMPLATE_REQUIRES( + size_t DynCount, size_t R, class OtherExtents, class... DynamicValues, + /* requires */ ((R < m_rank) && (static_extent(R) == dynamic_extent))) + MDSPAN_INLINE_FUNCTION + vals_t __construct_vals_from_extents(std::integral_constant, + std::integral_constant, + const OtherExtents &exts, + DynamicValues... dynamic_values) noexcept { + return __construct_vals_from_extents( + std::integral_constant(), + std::integral_constant(), exts, dynamic_values..., + exts.extent(R)); } - template - MDSPAN_FORCE_INLINE_FUNCTION - constexpr - index_type __extent() const noexcept { - return __storage().template __get_n(); + MDSPAN_TEMPLATE_REQUIRES( + size_t DynCount, size_t R, class OtherExtents, class... DynamicValues, + /* requires */ ((R < m_rank) && (static_extent(R) != dynamic_extent))) + MDSPAN_INLINE_FUNCTION + vals_t __construct_vals_from_extents(std::integral_constant, + std::integral_constant, + const OtherExtents &exts, + DynamicValues... dynamic_values) noexcept { + return __construct_vals_from_extents( + std::integral_constant(), + std::integral_constant(), exts, dynamic_values...); } - template + MDSPAN_TEMPLATE_REQUIRES( + size_t DynCount, size_t R, class OtherExtents, class... DynamicValues, + /* requires */ ((R == m_rank) && (DynCount == m_rank_dynamic))) MDSPAN_INLINE_FUNCTION - static constexpr - index_type __static_extent() noexcept { - return __storage_t::template __get_static_n(); + vals_t __construct_vals_from_extents(std::integral_constant, + std::integral_constant, + const OtherExtents &, + DynamicValues... dynamic_values) noexcept { + return vals_t{static_cast(dynamic_values)...}; } +public: + + // Converting constructor from other extents specializations + MDSPAN_TEMPLATE_REQUIRES( + class OtherIndexType, size_t... OtherExtents, + /* requires */ + ( + /* multi-stage check to protect from invalid pack expansion when sizes + don't match? */ + decltype(detail::__check_compatible_extents( + std::integral_constant{}, + std::integer_sequence{}, + std::integer_sequence{}))::value)) + MDSPAN_INLINE_FUNCTION + MDSPAN_CONDITIONAL_EXPLICIT((((Extents != dynamic_extent) && + (OtherExtents == dynamic_extent)) || + ...) || + (std::numeric_limits::max() < + std::numeric_limits::max())) + constexpr extents(const extents &other) noexcept + : m_vals(__construct_vals_from_extents( + std::integral_constant(), + std::integral_constant(), other)) {} + + // Comparison operator + template + MDSPAN_INLINE_FUNCTION friend constexpr bool + operator==(const extents &lhs, + const extents &rhs) noexcept { + bool value = true; + for (size_type r = 0; r < m_rank; r++) + value &= rhs.extent(r) == lhs.extent(r); + return value; + } + +#if !(MDSPAN_HAS_CXX_20) + template + MDSPAN_INLINE_FUNCTION friend constexpr bool + operator!=(extents const &lhs, + extents const &rhs) noexcept { + return !(lhs == rhs); + } +#endif }; +// Recursive helper classes to implement dextents alias for extents namespace detail { -template > +template > struct __make_dextents; template -struct __make_dextents> { - using type = typename __make_dextents>::type; +struct __make_dextents< + IndexType, Rank, ::std::experimental::extents> { + using type = typename __make_dextents< + IndexType, Rank - 1, + ::std::experimental::extents>::type; }; template -struct __make_dextents> { +struct __make_dextents< + IndexType, 0, ::std::experimental::extents> { using type = ::std::experimental::extents; }; } // end namespace detail +// [mdspan.extents.dextents], alias template template using dextents = typename detail::__make_dextents::type; +// Deduction guide for extents #if defined(_MDSPAN_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) template extents(IndexTypes...) - -> extents; + -> extents; #endif +// Helper type traits for identifying a class as extents. namespace detail { -template -struct __is_extents : ::std::false_type {}; +template struct __is_extents : ::std::false_type {}; template -struct __is_extents<::std::experimental::extents> : ::std::true_type {}; +struct __is_extents<::std::experimental::extents> + : ::std::true_type {}; template -static constexpr bool __is_extents_v = __is_extents::value; - - -template -struct __extents_to_partially_static_sizes; - -template -struct __extents_to_partially_static_sizes<::std::experimental::extents> { - using type = detail::__partially_static_sizes< - typename ::std::experimental::extents::index_type, size_t, - ExtentsPack...>; -}; - -template -using __extents_to_partially_static_sizes_t = typename __extents_to_partially_static_sizes::type; +#if MDSPAN_HAS_CXX_17 +inline +#else +static +#endif +constexpr bool __is_extents_v = __is_extents::value; -} // end namespace detail -} // end namespace experimental -} // end namespace std +} // namespace detail +} // namespace experimental +} // namespace std diff --git a/include/experimental/__p0009_bits/layout_left.hpp b/include/experimental/__p0009_bits/layout_left.hpp index a23a905c..0bfa5680 100644 --- a/include/experimental/__p0009_bits/layout_left.hpp +++ b/include/experimental/__p0009_bits/layout_left.hpp @@ -48,7 +48,7 @@ class layout_left::mapping { constexpr index_type __compute_offset( __rank_count, const I& i, Indices... idx) const { return __compute_offset(__rank_count(), idx...) * - __extents.template __extent() + i; + __extents.extent(r) + i; } template diff --git a/include/experimental/__p0009_bits/layout_right.hpp b/include/experimental/__p0009_bits/layout_right.hpp index 634024af..a3f3ab86 100644 --- a/include/experimental/__p0009_bits/layout_right.hpp +++ b/include/experimental/__p0009_bits/layout_right.hpp @@ -48,7 +48,7 @@ class layout_right::mapping { _MDSPAN_HOST_DEVICE constexpr index_type __compute_offset( index_type offset, __rank_count, const I& i, Indices... idx) const { - return __compute_offset(offset * __extents.template __extent() + i,__rank_count(), idx...); + return __compute_offset(offset * __extents.extent(r) + i,__rank_count(), idx...); } template diff --git a/include/experimental/__p0009_bits/layout_stride.hpp b/include/experimental/__p0009_bits/layout_stride.hpp index d53b5fe0..cac4f900 100644 --- a/include/experimental/__p0009_bits/layout_stride.hpp +++ b/include/experimental/__p0009_bits/layout_stride.hpp @@ -16,7 +16,6 @@ #pragma once #include "macros.hpp" -#include "static_array.hpp" #include "extents.hpp" #include "trait_backports.hpp" #include "compressed_pair.hpp" @@ -189,13 +188,6 @@ struct layout_stride { } #endif - MDSPAN_INLINE_FUNCTION - static constexpr const __strides_storage_t fill_strides( - detail::__extents_to_partially_static_sizes_t< - ::std::experimental::dextents>&& s) { - return __strides_storage_t{static_cast(s.template __get_n())...}; - } - template MDSPAN_INLINE_FUNCTION static constexpr size_t __return_zero() { return 0; } @@ -220,31 +212,6 @@ struct layout_stride { mapping(__base_t&& __b) : __base_t(::std::move(__b)) {} #endif - public: // but not really - MDSPAN_INLINE_FUNCTION - static constexpr mapping - __make_mapping( - detail::__extents_to_partially_static_sizes_t&& __exts, - detail::__extents_to_partially_static_sizes_t< - ::std::experimental::dextents>&& __strs - ) noexcept { - // call the private constructor we created for this purpose - return mapping( -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - __base_t{ -#endif - __member_pair_t( - extents_type::__make_extents_impl(::std::move(__exts)), - __strides_storage_t{__impl::fill_strides(::std::move(__strs))} - ) -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#endif - ); - } - //---------------------------------------------------------------------------- - - public: //-------------------------------------------------------------------------------- diff --git a/include/experimental/__p0009_bits/maybe_static_value.hpp b/include/experimental/__p0009_bits/maybe_static_value.hpp deleted file mode 100644 index 5e4437fd..00000000 --- a/include/experimental/__p0009_bits/maybe_static_value.hpp +++ /dev/null @@ -1,124 +0,0 @@ -//@HEADER -// ************************************************************************ -// -// Kokkos v. 4.0 -// Copyright (2022) National Technology & Engineering -// Solutions of Sandia, LLC (NTESS). -// -// Under the terms of Contract DE-NA0003525 with NTESS, -// the U.S. Government retains certain rights in this software. -// -// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. -// See https://kokkos.org/LICENSE for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//@HEADER -#include "macros.hpp" - -#include "dynamic_extent.hpp" - -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) -# include "no_unique_address.hpp" -#endif - -// This is only needed for the non-standard-layout version of partially -// static array. -// Needs to be after the includes above to work with the single header generator -#if !_MDSPAN_PRESERVE_STANDARD_LAYOUT -namespace std { -namespace experimental { - -//============================================================================== - -namespace detail { - -// static case -template -struct __maybe_static_value { - static constexpr _static_t __static_value = __v; - MDSPAN_FORCE_INLINE_FUNCTION constexpr _dynamic_t __value() const noexcept { - return static_cast<_dynamic_t>(__v); - } - template - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 - __mdspan_enable_fold_comma - __set_value(_U&& /*__rhs*/) noexcept { - // Should we assert that the value matches the static value here? - return {}; - } - - //-------------------------------------------------------------------------- - - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __maybe_static_value() noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __maybe_static_value(__maybe_static_value const&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __maybe_static_value(__maybe_static_value&&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __maybe_static_value& operator=(__maybe_static_value const&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __maybe_static_value& operator=(__maybe_static_value&&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - ~__maybe_static_value() noexcept = default; - - MDSPAN_INLINE_FUNCTION - constexpr explicit __maybe_static_value(_dynamic_t const&) noexcept { - // Should we assert that the value matches the static value here? - } - - //-------------------------------------------------------------------------- - -}; - -// dynamic case -template -struct __maybe_static_value<_dynamic_t, _static_t, __is_dynamic_sentinal, __is_dynamic_sentinal, - __array_entry_index> -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __no_unique_address_emulation<_T> -#endif -{ - static constexpr _static_t __static_value = __is_dynamic_sentinal; -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - _MDSPAN_NO_UNIQUE_ADDRESS _dynamic_t __v = {}; - MDSPAN_FORCE_INLINE_FUNCTION constexpr _dynamic_t __value() const noexcept { - return __v; - } - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _dynamic_t &__ref() noexcept { - return __v; - } - template - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 - __mdspan_enable_fold_comma - __set_value(_U&& __rhs) noexcept { - __v = (_U &&)rhs; - return {}; - } -#else - MDSPAN_FORCE_INLINE_FUNCTION constexpr _dynamic_t __value() const noexcept { - return this->__no_unique_address_emulation<_dynamic_t>::__ref(); - } - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _dynamic_t &__ref() noexcept { - return this->__no_unique_address_emulation<_dynamic_t>::__ref(); - } - template - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 - __mdspan_enable_fold_comma - __set_value(_U&& __rhs) noexcept { - this->__no_unique_address_emulation<_dynamic_t>::__ref() = (_U &&)__rhs; - return {}; - } -#endif -}; - -} // namespace detail - -//============================================================================== - -} // end namespace experimental -} // end namespace std - -#endif // !_MDSPAN_PRESERVE_STANDARD_LAYOUT diff --git a/include/experimental/__p0009_bits/mdspan.hpp b/include/experimental/__p0009_bits/mdspan.hpp index 928ef631..c81a8836 100644 --- a/include/experimental/__p0009_bits/mdspan.hpp +++ b/include/experimental/__p0009_bits/mdspan.hpp @@ -45,11 +45,11 @@ class mdspan { MDSPAN_FORCE_INLINE_FUNCTION static constexpr size_t __size(mdspan const& __self) noexcept { - return _MDSPAN_FOLD_TIMES_RIGHT((__self.__mapping_ref().extents().template __extent()), /* * ... * */ size_t(1)); + return _MDSPAN_FOLD_TIMES_RIGHT((__self.__mapping_ref().extents().extent(Idxs)), /* * ... * */ size_t(1)); } MDSPAN_FORCE_INLINE_FUNCTION static constexpr bool __empty(mdspan const& __self) noexcept { - return (__self.rank()>0) && _MDSPAN_FOLD_OR((__self.__mapping_ref().extents().template __extent()==index_type(0))); + return (__self.rank()>0) && _MDSPAN_FOLD_OR((__self.__mapping_ref().extents().extent(Idxs)==index_type(0))); } template MDSPAN_FORCE_INLINE_FUNCTION static constexpr @@ -97,7 +97,8 @@ class mdspan #else MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mdspan() requires( - (rank_dynamic() > 0) && + // nvhpc has a bug where using just rank_dynamic() here doesn't work ... + (extents_type::rank_dynamic() > 0) && _MDSPAN_TRAIT(is_default_constructible, data_handle_type) && _MDSPAN_TRAIT(is_default_constructible, mapping_type) && _MDSPAN_TRAIT(is_default_constructible, accessor_type) @@ -322,7 +323,7 @@ class mdspan MDSPAN_INLINE_FUNCTION friend constexpr void swap(mdspan& x, mdspan& y) noexcept { // can't call the std::swap inside on HIP - #ifndef _MDSPAN_HAS_HIP + #if !defined(_MDSPAN_HAS_HIP) && !defined(_MDSPAN_HAS_CUDA) swap(x.__ptr_ref(), y.__ptr_ref()); swap(x.__mapping_ref(), y.__mapping_ref()); swap(x.__accessor_ref(), y.__accessor_ref()); diff --git a/include/experimental/__p0009_bits/standard_layout_static_array.hpp b/include/experimental/__p0009_bits/standard_layout_static_array.hpp deleted file mode 100644 index c515ccc0..00000000 --- a/include/experimental/__p0009_bits/standard_layout_static_array.hpp +++ /dev/null @@ -1,657 +0,0 @@ -//@HEADER -// ************************************************************************ -// -// Kokkos v. 4.0 -// Copyright (2022) National Technology & Engineering -// Solutions of Sandia, LLC (NTESS). -// -// Under the terms of Contract DE-NA0003525 with NTESS, -// the U.S. Government retains certain rights in this software. -// -// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. -// See https://kokkos.org/LICENSE for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//@HEADER -#pragma once - -#include "macros.hpp" -#include "dynamic_extent.hpp" -#include "trait_backports.hpp" // enable_if -#include "compressed_pair.hpp" - -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) -# include "no_unique_address.hpp" -#endif - -#include -#ifdef __cpp_lib_span -#include -#endif -#include // integer_sequence -#include - -namespace std { -namespace experimental { -namespace detail { - -//============================================================================== - -_MDSPAN_INLINE_VARIABLE constexpr struct - __construct_psa_from_dynamic_exts_values_tag_t { -} __construct_psa_from_dynamic_exts_values_tag = {}; - -_MDSPAN_INLINE_VARIABLE constexpr struct - __construct_psa_from_all_exts_values_tag_t { -} __construct_psa_from_all_exts_values_tag = {}; - -struct __construct_psa_from_all_exts_array_tag_t {}; -template struct __construct_psa_from_dynamic_exts_array_tag_t {}; - -//============================================================================== - -template using __repeated_with_idxs = _T; - -//============================================================================== - -#if _MDSPAN_PRESERVE_STANDARD_LAYOUT - -/** - * PSA = "partially static array" - * - * @tparam _T - * @tparam _ValsSeq - * @tparam __sentinal - */ -template (dynamic_extent), - class _IdxsSeq = make_index_sequence<_ValsSeq::size()>> -struct __standard_layout_psa; - -//============================================================================== -// Static case -template -struct __standard_layout_psa< - _Tag, _T, _static_t, integer_sequence<_static_t, __value, __values_or_sentinals...>, - __sentinal, integer_sequence> -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : private __no_unique_address_emulation<__standard_layout_psa< - _Tag, _T, _static_t, integer_sequence<_static_t, __values_or_sentinals...>, __sentinal, - integer_sequence>> -#endif -{ - - //-------------------------------------------------------------------------- - - using __next_t = - __standard_layout_psa<_Tag, _T, _static_t, - integer_sequence<_static_t, __values_or_sentinals...>, - __sentinal, integer_sequence>; - -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - _MDSPAN_NO_UNIQUE_ADDRESS __next_t __next_; -#else - using __base_t = __no_unique_address_emulation<__next_t>; -#endif - - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 __next_t &__next() noexcept { -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - return __next_; -#else - return this->__base_t::__ref(); -#endif - } - MDSPAN_FORCE_INLINE_FUNCTION constexpr __next_t const &__next() const noexcept { -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - return __next_; -#else - return this->__base_t::__ref(); -#endif - } - - static constexpr auto __size = sizeof...(_Idxs) + 1; - static constexpr auto __size_dynamic = __next_t::__size_dynamic; - - //-------------------------------------------------------------------------- - - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __standard_layout_psa() noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __standard_layout_psa(__standard_layout_psa const &) noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __standard_layout_psa(__standard_layout_psa &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __standard_layout_psa & - operator=(__standard_layout_psa const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __standard_layout_psa & - operator=(__standard_layout_psa &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - ~__standard_layout_psa() noexcept = default; - - //-------------------------------------------------------------------------- - - MDSPAN_INLINE_FUNCTION - constexpr __standard_layout_psa( - __construct_psa_from_all_exts_values_tag_t, _T const & /*__val*/, - __repeated_with_idxs<_Idxs, _T> const &... __vals) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __next_{ -#else - : __base_t(__base_t{__next_t( -#endif - __construct_psa_from_all_exts_values_tag, __vals... -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#else - )}) -#endif - { } - - template - MDSPAN_INLINE_FUNCTION constexpr __standard_layout_psa( - __construct_psa_from_dynamic_exts_values_tag_t, - _Ts const &... __vals) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __next_{ -#else - : __base_t(__base_t{__next_t( -#endif - __construct_psa_from_dynamic_exts_values_tag, __vals... -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#else - )}) -#endif - { } - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - array<_U, _N> const &__vals) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __next_{ -#else - : __base_t(__base_t{__next_t( -#endif - __vals -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#else - )}) -#endif - { } - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - __construct_psa_from_all_exts_array_tag_t const & __tag, - array<_U, _NStatic> const &__vals) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __next_{ -#else - : __base_t(__base_t{__next_t( -#endif - __tag, __vals -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#else - )}) -#endif - { } - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - __construct_psa_from_dynamic_exts_array_tag_t<_IDynamic> __tag, - array<_U, _NDynamic> const &__vals) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __next_{ -#else - : __base_t(__base_t{__next_t( -#endif - __tag, __vals -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#else - )}) -#endif - { } - -#ifdef __cpp_lib_span - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - span<_U, _N> const &__vals) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __next_{ -#else - : __base_t(__base_t{__next_t( -#endif - __vals -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#else - )}) -#endif - { } - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - __construct_psa_from_all_exts_array_tag_t const & __tag, - span<_U, _NStatic> const &__vals) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __next_{ -#else - : __base_t(__base_t{__next_t( -#endif - __tag, __vals -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#else - )}) -#endif - { } - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - __construct_psa_from_dynamic_exts_array_tag_t<_IDynamic> __tag, - span<_U, _NDynamic> const &__vals) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __next_{ -#else - : __base_t(__base_t{__next_t( -#endif - __tag, __vals -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#else - )}) -#endif - { } -#endif - - template - MDSPAN_INLINE_FUNCTION constexpr __standard_layout_psa( - __standard_layout_psa<_UTag, _U, _static_U, _UValsSeq, __u_sentinal, _IdxsSeq> const - &__rhs) noexcept -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : __next_{ -#else - : __base_t(__base_t{__next_t( -#endif - __rhs.__next() -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#else - )}) -#endif - { } - - //-------------------------------------------------------------------------- - - // See https://godbolt.org/z/_KSDNX for a summary-by-example of why this is - // necessary. We're using inheritance here instead of an alias template - // because we have to deduce __values_or_sentinals in several places, and - // alias templates don't permit that in this context. - MDSPAN_FORCE_INLINE_FUNCTION - constexpr __standard_layout_psa const &__enable_psa_conversion() const - noexcept { - return *this; - } - - template = 0> - MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get_n() const noexcept { - return __next().template __get_n<_I>(); - } - template = 1> - MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get_n() const noexcept { - return __value; - } - template = 0> - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 void - __set_n(_T const &__rhs) noexcept { - __next().__set_value(__rhs); - } - template = 1> - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 void - __set_n(_T const &) noexcept { - // Don't assert here because that would break constexpr. This better - // not change anything, though - } - template = __sentinal> - MDSPAN_FORCE_INLINE_FUNCTION static constexpr _static_t __get_static_n() noexcept { - return __value; - } - template __default = __sentinal> - MDSPAN_FORCE_INLINE_FUNCTION static constexpr _static_t __get_static_n() noexcept { - return __next_t::template __get_static_n<_I, __default>(); - } - MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get(size_t __n) const noexcept { - return __value * (_T(_Idx == __n)) + __next().__get(__n); - } - - //-------------------------------------------------------------------------- -}; - -//============================================================================== - -// Dynamic case, __next_t may or may not be empty -template -struct __standard_layout_psa< - _Tag, _T, _static_t, integer_sequence<_static_t, __sentinal, __values_or_sentinals...>, - __sentinal, integer_sequence> { - //-------------------------------------------------------------------------- - - using __next_t = - __standard_layout_psa<_Tag, _T, _static_t, - integer_sequence<_static_t, __values_or_sentinals...>, - __sentinal, integer_sequence>; - - using __value_pair_t = __compressed_pair<_T, __next_t>; - __value_pair_t __value_pair; - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 __next_t &__next() noexcept { - return __value_pair.__second(); - } - MDSPAN_FORCE_INLINE_FUNCTION constexpr __next_t const &__next() const noexcept { - return __value_pair.__second(); - } - - static constexpr auto __size = sizeof...(_Idxs) + 1; - static constexpr auto __size_dynamic = 1 + __next_t::__size_dynamic; - - //-------------------------------------------------------------------------- - - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __standard_layout_psa() noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __standard_layout_psa(__standard_layout_psa const &) noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __standard_layout_psa(__standard_layout_psa &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __standard_layout_psa & - operator=(__standard_layout_psa const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __standard_layout_psa & - operator=(__standard_layout_psa &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - ~__standard_layout_psa() noexcept = default; - - //-------------------------------------------------------------------------- - - MDSPAN_INLINE_FUNCTION - constexpr __standard_layout_psa( - __construct_psa_from_all_exts_values_tag_t, _T const &__val, - __repeated_with_idxs<_Idxs, _T> const &... __vals) noexcept - : __value_pair(__val, - __next_t(__construct_psa_from_all_exts_values_tag, - __vals...)) {} - - template - MDSPAN_INLINE_FUNCTION constexpr __standard_layout_psa( - __construct_psa_from_dynamic_exts_values_tag_t, _T const &__val, - _Ts const &... __vals) noexcept - : __value_pair(__val, - __next_t(__construct_psa_from_dynamic_exts_values_tag, - __vals...)) {} - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - array<_U, _N> const &__vals) noexcept - : __value_pair(::std::get<_Idx>(__vals), __vals) {} - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - __construct_psa_from_all_exts_array_tag_t __tag, - array<_U, _NStatic> const &__vals) noexcept - : __value_pair( - ::std::get<_Idx>(__vals), - __next_t(__tag, - __vals)) {} - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - __construct_psa_from_dynamic_exts_array_tag_t<_IDynamic>, - array<_U, _NDynamic> const &__vals) noexcept - : __value_pair( - ::std::get<_IDynamic>(__vals), - __next_t(__construct_psa_from_dynamic_exts_array_tag_t<_IDynamic + 1>{}, - __vals)) {} - -#ifdef __cpp_lib_span - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - span<_U, _N> const &__vals) noexcept - : __value_pair(__vals[_Idx], __vals) {} - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - __construct_psa_from_all_exts_array_tag_t __tag, - span<_U, _NStatic> const &__vals) noexcept - : __value_pair( - __vals[_Idx], - __next_t(__tag, - __vals)) {} - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - __construct_psa_from_dynamic_exts_array_tag_t<_IDynamic>, - span<_U, _NDynamic> const &__vals) noexcept - : __value_pair( - __vals[_IDynamic], - __next_t(__construct_psa_from_dynamic_exts_array_tag_t<_IDynamic + 1>{}, - __vals)) {} -#endif - - template - MDSPAN_INLINE_FUNCTION constexpr __standard_layout_psa( - __standard_layout_psa<_UTag, _U, _static_U, _UValsSeq, __u_sentinal, _UIdxsSeq> const - &__rhs) noexcept - : __value_pair(__rhs.template __get_n<_Idx>(), __rhs.__next()) {} - - //-------------------------------------------------------------------------- - - // See comment in the previous partial specialization for why this is - // necessary. Or just trust me that it's messy. - MDSPAN_FORCE_INLINE_FUNCTION - constexpr __standard_layout_psa const &__enable_psa_conversion() const - noexcept { - return *this; - } - - template = 0> - MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get_n() const noexcept { - return __next().template __get_n<_I>(); - } - template = 1> - MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get_n() const noexcept { - return __value_pair.__first(); - } - template = 0> - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 void - __set_n(_T const &__rhs) noexcept { - __next().__set_value(__rhs); - } - template = 1> - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 void - __set_n(_T const &__rhs) noexcept { - __value_pair.__first() = __rhs; - } - template __default = __sentinal> - MDSPAN_FORCE_INLINE_FUNCTION static constexpr _static_t __get_static_n() noexcept { - return __default; - } - template __default = __sentinal> - MDSPAN_FORCE_INLINE_FUNCTION static constexpr _static_t __get_static_n() noexcept { - return __next_t::template __get_static_n<_I, __default>(); - } - MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get(size_t __n) const noexcept { - return __value_pair.__first() * (_T(_Idx == __n)) + __next().__get(__n); - } - - //-------------------------------------------------------------------------- -}; - -// empty/terminal case -template -struct __standard_layout_psa<_Tag, _T, _static_t, integer_sequence<_static_t>, __sentinal, - integer_sequence> { - //-------------------------------------------------------------------------- - - static constexpr auto __size = 0; - static constexpr auto __size_dynamic = 0; - - //-------------------------------------------------------------------------- - - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __standard_layout_psa() noexcept -#if defined(__clang__) || defined(_MDSPAN_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND) - // As far as I can tell, there appears to be a bug in clang that's causing - // this to be non-constexpr when it's defaulted. - { } -#else - = default; -#endif - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __standard_layout_psa(__standard_layout_psa const &) noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __standard_layout_psa(__standard_layout_psa &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __standard_layout_psa & - operator=(__standard_layout_psa const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __standard_layout_psa & - operator=(__standard_layout_psa &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - ~__standard_layout_psa() noexcept = default; - - MDSPAN_INLINE_FUNCTION - constexpr __standard_layout_psa( - __construct_psa_from_all_exts_values_tag_t) noexcept {} - - template - MDSPAN_INLINE_FUNCTION constexpr __standard_layout_psa( - __construct_psa_from_dynamic_exts_values_tag_t) noexcept {} - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - array<_U, _N> const &) noexcept {} - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - __construct_psa_from_all_exts_array_tag_t, - array<_U, _NStatic> const &) noexcept {} - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - __construct_psa_from_dynamic_exts_array_tag_t<_IDynamic>, - array<_U, _NDynamic> const &) noexcept {} - -#ifdef __cpp_lib_span - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - span<_U, _N> const &) noexcept {} - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - __construct_psa_from_all_exts_array_tag_t, - span<_U, _NStatic> const &) noexcept {} - - template - MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( - __construct_psa_from_dynamic_exts_array_tag_t<_IDynamic>, - span<_U, _NDynamic> const &) noexcept {} -#endif - - template - MDSPAN_INLINE_FUNCTION constexpr __standard_layout_psa( - __standard_layout_psa<_UTag, _U, _static_U, _UValsSeq, __u_sentinal, _UIdxsSeq> const&) noexcept {} - - // See comment in the previous partial specialization for why this is - // necessary. Or just trust me that it's messy. - MDSPAN_FORCE_INLINE_FUNCTION - constexpr __standard_layout_psa const &__enable_psa_conversion() const - noexcept { - return *this; - } - - MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get(size_t /*n*/) const noexcept { - return 0; - } -}; - -// Same thing, but with a disambiguator so that same-base issues doesn't cause -// a loss of standard-layout-ness. -template -struct __partially_static_sizes_tagged - : __standard_layout_psa< - _Tag, T, _static_t, - integer_sequence<_static_t, __values_or_sentinals...>> { - using __tag_t = _Tag; - using __psa_impl_t = __standard_layout_psa< - _Tag, T, _static_t, integer_sequence<_static_t, __values_or_sentinals...>>; - using __psa_impl_t::__psa_impl_t; -#ifdef _MDSPAN_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND - MDSPAN_INLINE_FUNCTION -#endif - constexpr __partially_static_sizes_tagged() noexcept -#ifdef _MDSPAN_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND - : __psa_impl_t() { } -#else - = default; -#endif - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __partially_static_sizes_tagged( - __partially_static_sizes_tagged const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __partially_static_sizes_tagged( - __partially_static_sizes_tagged &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __partially_static_sizes_tagged & - operator=(__partially_static_sizes_tagged const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __partially_static_sizes_tagged & - operator=(__partially_static_sizes_tagged &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - ~__partially_static_sizes_tagged() noexcept = default; - - template - MDSPAN_FORCE_INLINE_FUNCTION constexpr explicit __partially_static_sizes_tagged( - __partially_static_sizes_tagged<_UTag, T, _static_t, __values_or_sentinals...> const& __vals - ) noexcept : __psa_impl_t(__vals.__enable_psa_conversion()) { } -}; - -struct __no_tag {}; -template -struct __partially_static_sizes - : __partially_static_sizes_tagged<__no_tag, T, _static_t, __values_or_sentinals...> { -private: - using __base_t = - __partially_static_sizes_tagged<__no_tag, T, _static_t, __values_or_sentinals...>; - template - MDSPAN_FORCE_INLINE_FUNCTION constexpr __partially_static_sizes( - __partially_static_sizes_tagged<_UTag, T, _static_t, __values_or_sentinals...>&& __vals - ) noexcept : __base_t(::std::move(__vals)) { } -public: - using __base_t::__base_t; - -#ifdef _MDSPAN_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND - MDSPAN_INLINE_FUNCTION - constexpr __partially_static_sizes() noexcept : __base_t() { } -#endif - template - MDSPAN_FORCE_INLINE_FUNCTION constexpr __partially_static_sizes_tagged< - _UTag, T, _static_t, __values_or_sentinals...> - __with_tag() const noexcept { - return __partially_static_sizes_tagged<_UTag, T, _static_t, __values_or_sentinals...>(*this); - } -}; - -#endif // _MDSPAN_PRESERVE_STATIC_LAYOUT - -} // end namespace detail -} // end namespace experimental -} // end namespace std diff --git a/include/experimental/__p0009_bits/static_array.hpp b/include/experimental/__p0009_bits/static_array.hpp deleted file mode 100644 index fe9322f6..00000000 --- a/include/experimental/__p0009_bits/static_array.hpp +++ /dev/null @@ -1,258 +0,0 @@ -//@HEADER -// ************************************************************************ -// -// Kokkos v. 4.0 -// Copyright (2022) National Technology & Engineering -// Solutions of Sandia, LLC (NTESS). -// -// Under the terms of Contract DE-NA0003525 with NTESS, -// the U.S. Government retains certain rights in this software. -// -// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. -// See https://kokkos.org/LICENSE for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//@HEADER -#pragma once - -#include "macros.hpp" - -#include "dynamic_extent.hpp" -#include "trait_backports.hpp" -#include "maybe_static_value.hpp" -#include "standard_layout_static_array.hpp" -#include "type_list.hpp" - -// Needs to be after the includes above to work with the single header generator -#if !_MDSPAN_PRESERVE_STANDARD_LAYOUT -#include // size_t -#include // integer_sequence -#include - -namespace std { -namespace experimental { -namespace detail { - -//============================================================================== - -template struct __mask_element {}; - -template -struct __mask_sequence_assign_op { - template <_T _V> - __mask_sequence_assign_op<_T, _Result..., _V> - operator=(__mask_element<_T, _V, true>&&); - template <_T _V> - __mask_sequence_assign_op<_T, _Result...> - operator=(__mask_element<_T, _V, false>&&); - using __result = integer_sequence<_T, _Result...>; -}; - -template -struct __mask_sequence; - -template -struct __mask_sequence, integer_sequence> -{ - using type = typename decltype( - _MDSPAN_FOLD_ASSIGN_LEFT( - __mask_sequence_assign_op<_T>{}, /* = ... = */ __mask_element<_T, _Vals, _Masks>{} - ) - )::__result; -}; - -//============================================================================== - -template -class __partially_static_array_impl; - -template < - class _T, class _static_t, - _static_t... __values_or_sentinals, _static_t __sentinal, - size_t... _Idxs, - size_t... _IdxsDynamic, - size_t... _IdxsDynamicIdxs -> -class __partially_static_array_impl< - _T, - _static_t, - integer_sequence<_static_t, __values_or_sentinals...>, - __sentinal, - integer_sequence, - integer_sequence, - integer_sequence -> - : private __maybe_static_value<_T, _static_t, __values_or_sentinals, __sentinal, - _Idxs>... { -private: - - template - using __base_n = typename __type_at<_N, - __type_list<__maybe_static_value<_T, _static_t, __values_or_sentinals, __sentinal, _Idxs>...> - >::type; - -public: - - static constexpr auto __size = sizeof...(_Idxs); - static constexpr auto __size_dynamic = - _MDSPAN_FOLD_PLUS_RIGHT(static_cast((__values_or_sentinals == __sentinal)), /* + ... + */ 0); - - //-------------------------------------------------------------------------- - - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __partially_static_array_impl() = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __partially_static_array_impl( - __partially_static_array_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __partially_static_array_impl( - __partially_static_array_impl &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __partially_static_array_impl & - operator=(__partially_static_array_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __partially_static_array_impl & - operator=(__partially_static_array_impl &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - ~__partially_static_array_impl() noexcept = default; - - MDSPAN_INLINE_FUNCTION - constexpr __partially_static_array_impl( - __construct_psa_from_all_exts_values_tag_t, - __repeated_with_idxs<_Idxs, _T> const &... __vals) noexcept - : __base_n<_Idxs>(__base_n<_Idxs>{{__vals}})... {} - - MDSPAN_INLINE_FUNCTION - constexpr __partially_static_array_impl( - __construct_psa_from_dynamic_exts_values_tag_t, - __repeated_with_idxs<_IdxsDynamicIdxs, _T> const &... __vals) noexcept - : __base_n<_IdxsDynamic>(__base_n<_IdxsDynamic>{{__vals}})... {} - - MDSPAN_INLINE_FUNCTION constexpr explicit __partially_static_array_impl( - array<_T, sizeof...(_Idxs)> const& __vals) noexcept - : __partially_static_array_impl( - __construct_psa_from_all_exts_values_tag, - ::std::get<_Idxs>(__vals)...) {} - - // clang-format off - MDSPAN_FUNCTION_REQUIRES( - (MDSPAN_INLINE_FUNCTION constexpr explicit), - __partially_static_array_impl, - (array<_T, __size_dynamic> const &__vals), noexcept, - /* requires */ - (sizeof...(_Idxs) != __size_dynamic) - ): __partially_static_array_impl( - __construct_psa_from_dynamic_exts_values_tag, - ::std::get<_IdxsDynamicIdxs>(__vals)...) {} - // clang-format on - - template - MDSPAN_INLINE_FUNCTION constexpr __partially_static_array_impl( - __partially_static_array_impl< - _U, _static_u, _UValsSeq, __u_sentinal, _UIdxsSeq, - _UIdxsDynamicSeq, _UIdxsDynamicIdxsSeq> const &__rhs) noexcept - : __partially_static_array_impl( - __construct_psa_from_all_exts_values_tag, - __rhs.template __get_n<_Idxs>()...) {} - - //-------------------------------------------------------------------------- - - // See comment in the previous partial specialization for why this is - // necessary. Or just trust me that it's messy. - MDSPAN_FORCE_INLINE_FUNCTION - constexpr __partially_static_array_impl const &__enable_psa_conversion() const - noexcept { - return *this; - } - - template - MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get_n() const noexcept { - return static_cast<__base_n<_I> const*>(this)->__value(); - } - - template - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 void __set_n(_U&& __rhs) noexcept { - static_cast<__base_n<_I>*>(this)->__set_value((_U&&)__rhs); - } - - template - MDSPAN_FORCE_INLINE_FUNCTION static constexpr _static_t - __get_static_n() noexcept { - return __base_n<_I>::__static_value == __sentinal ? - __default : __base_n<_I>::__static_value; - } - - MDSPAN_FORCE_INLINE_FUNCTION constexpr _T - __get(size_t __n) const noexcept { - return _MDSPAN_FOLD_PLUS_RIGHT( - (_T(_Idxs == __n) * __get_n<_Idxs>()), /* + ... + */ _T(0) - ); - } - -}; - -//============================================================================== - -template > -struct __partially_static_array_impl_maker; - -template < - class _T, class _static_t, _static_t... _Vals, _static_t __sentinal, size_t... _Idxs -> -struct __partially_static_array_impl_maker< - _T, _static_t, integer_sequence<_static_t, _Vals...>, __sentinal, integer_sequence -> -{ - using __dynamic_idxs = typename __mask_sequence< - integer_sequence, - integer_sequence - >::type; - using __impl_base = - __partially_static_array_impl<_T, _static_t, - integer_sequence<_static_t, _Vals...>, - __sentinal, integer_sequence, - __dynamic_idxs, - make_index_sequence<__dynamic_idxs::size()> - >; -}; - -template -class __partially_static_array_with_sentinal - : public __partially_static_array_impl_maker<_T, _static_t, _ValsSeq, __sentinal>::__impl_base -{ -private: - using __base_t = typename __partially_static_array_impl_maker<_T, _static_t, _ValsSeq, __sentinal>::__impl_base; -public: - using __base_t::__base_t; -}; - -//============================================================================== - -template -struct __partially_static_sizes : - __partially_static_array_with_sentinal< - T, _static_t, ::std::integer_sequence<_static_t, __values_or_sentinals...>> -{ -private: - using __base_t = __partially_static_array_with_sentinal< - T, _static_t, ::std::integer_sequence<_static_t, __values_or_sentinals...>>; -public: - using __base_t::__base_t; - template - MDSPAN_FORCE_INLINE_FUNCTION constexpr __partially_static_sizes - __with_tag() const noexcept { - return *this; - } -}; - -// Tags are needed for the standard layout version, but not here -template -using __partially_static_sizes_tagged = __partially_static_sizes; - -} // end namespace detail -} // end namespace experimental -} // end namespace std - -#endif // !_MDSPAN_PRESERVE_STANDARD_LAYOUT diff --git a/include/experimental/mdspan b/include/experimental/mdspan index c9b1bd26..9a8d6778 100644 --- a/include/experimental/mdspan +++ b/include/experimental/mdspan @@ -25,7 +25,6 @@ #include "__p0009_bits/layout_left.hpp" #include "__p0009_bits/layout_right.hpp" #include "__p0009_bits/macros.hpp" -#include "__p0009_bits/static_array.hpp" #if MDSPAN_HAS_CXX_17 #include "__p2630_bits/submdspan.hpp" #endif diff --git a/tests/foo_customizations.hpp b/tests/foo_customizations.hpp index 070bf9c6..87338486 100644 --- a/tests/foo_customizations.hpp +++ b/tests/foo_customizations.hpp @@ -24,7 +24,7 @@ namespace Foo { struct foo_ptr { T* data; MDSPAN_INLINE_FUNCTION - foo_ptr(T* ptr):data(ptr) {} + constexpr foo_ptr(T* ptr):data(ptr) {} }; template @@ -57,6 +57,7 @@ namespace Foo { } int* flag; + MDSPAN_INLINE_FUNCTION friend constexpr void swap(foo_accessor& x, foo_accessor& y) { x.flag[0] = 99; y.flag[0] = 77; diff --git a/tests/test_mdspan_swap.cpp b/tests/test_mdspan_swap.cpp index 31538fea..09085f30 100644 --- a/tests/test_mdspan_swap.cpp +++ b/tests/test_mdspan_swap.cpp @@ -102,9 +102,9 @@ TEST(TestMDSpanSwap, std_swap_dynamic_extents) { __MDSPAN_TESTS_RUN_TEST(test_mdspan_std_swap_dynamic_extents()) } -// On HIP we actually don't call through to swap via ADL +// On HIP/CUDA we actually don't call through to swap via ADL // so the foo swap test which has side effects will fail -#ifndef _MDSPAN_HAS_HIP +#if !defined(_MDSPAN_HAS_HIP) && !defined(_MDSPAN_HAS_CUDA) void test_mdspan_foo_swap_dynamic_extents() { size_t* errors = allocate_array(1); errors[0] = 0;