From 08a38fd42fb14d8d97f738feeae7a2832033328f Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Mon, 21 Nov 2022 17:04:58 -0700 Subject: [PATCH 01/33] Add new implementation of extents and maybe_static_array --- .../experimental/__p0009_bits/extents2.hpp | 354 ++++++++++++++++++ 1 file changed, 354 insertions(+) create mode 100644 include/experimental/__p0009_bits/extents2.hpp diff --git a/include/experimental/__p0009_bits/extents2.hpp b/include/experimental/__p0009_bits/extents2.hpp new file mode 100644 index 00000000..81403e37 --- /dev/null +++ b/include/experimental/__p0009_bits/extents2.hpp @@ -0,0 +1,354 @@ +#include "dynamic_extent.hpp" +#include "span" + +#define _MDSPAN_NEW_EXTENTS + +namespace std::experimental { + +// Implementation of Static Array, recursive implementation of get +template +struct static_array_impl; + +template +struct static_array_impl { + constexpr static T value(size_t r) { + if(r==R) return FirstExt; + else return static_array_impl::value(r); + } + template + constexpr static T get() { + if constexpr (r==R) return FirstExt; + else return static_array_impl::template get(); + } +}; + +// End the recursion +template +struct static_array_impl { + constexpr static T value(int) { + return FirstExt; + } + template + constexpr static T get() { + return FirstExt; + } +}; + +// Don't start recursion if size 0 +template +struct static_array_impl<0, T> { + constexpr static T value(int) { + return T(); + } + template + constexpr static T get() { + return T(); + } +}; + +// Static array, provides get(), get(r) and operator[r] +template +struct static_array { +private: + using impl_t = static_array_impl<0, T, Values...>; +public: + using value_type = T; + + constexpr T operator[](int r) const { return get(r); } + constexpr static T get(int r) { return impl_t::value(r); } + template + constexpr static T get() { return impl_t::template get(); } + constexpr static size_t size() { return sizeof...(Values); } +}; + +// index_sequence_scan takes indicies and provides get(r) and get() to get the sum of the first r-1 values +template +struct index_sequence_scan_impl; + +template +struct index_sequence_scan_impl { + constexpr static size_t get(int r) { + if(r>R) return FirstVal + index_sequence_scan_impl::get(r); + else return 0; + } + template + constexpr static size_t get() { return r>R? FirstVal + index_sequence_scan_impl::get(r):0; } +}; + +template +struct index_sequence_scan_impl { + constexpr static size_t get(int r) { return R>r?FirstVal:0; } + template + constexpr static size_t get() { return R>r?FirstVal:0; } +}; +template<> +struct index_sequence_scan_impl<0> { + constexpr static size_t get(int) { return 0; } + template + constexpr static size_t get() { return 0; } +}; + +// Need this to have fully empty class maybe_static_array with all entries static +// Rather specialize this small helper class on size 0, then the whole thing +template +struct possibly_empty_array { + T vals[N]; + constexpr T& operator[] (int r) { return vals[r]; } + constexpr const T& operator[] (int r) const { return vals[r]; } +}; + +template +struct possibly_empty_array { + constexpr T operator[] (int) { return T(); } + constexpr const T operator[] (int) const { return T(); } +}; + + +// maybe_static_array is an array which has a mix of static and dynamic values +template +struct maybe_static_array { + private: + using static_vals_t = static_array; + constexpr static size_t m_size = sizeof...(Values); + constexpr static size_t m_size_dynamic = ((Values==dyn_tag) + ... + 0); + + _MDSPAN_NO_UNIQUE_ADDRESS possibly_empty_array m_dyn_vals; + public: + using dyn_map_t = index_sequence_scan_impl<0, size_t(Values==dyn_tag)...>; + + using value_type = TDynamic; + using static_value_type = TStatic; + constexpr static static_value_type tag_value = dyn_tag; + + constexpr maybe_static_array() = default; + + // constructors from dynamic_extentamic values only + template + requires(sizeof...(DynVals)==m_size_dynamic && m_size_dynamic>0) + constexpr maybe_static_array(DynVals ... vals): + m_dyn_vals{static_cast(vals)...} {} + + template + requires(m_size_dynamic==0) + constexpr maybe_static_array(DynVals ...): + m_dyn_vals{} {} + + template + requires(N==m_size_dynamic && N>0) + constexpr maybe_static_array(const std::array& vals) { + for(int r=0; r(vals[r]); + } + template + requires(N==m_size_dynamic && N==0) + constexpr maybe_static_array(const std::array&) { + } + + template + requires(N==m_size_dynamic) + constexpr maybe_static_array(const std::span& vals) { + for(int r=0; r(vals[r]); + } + + // constructors from all values + template + requires(sizeof...(DynVals)!=m_size_dynamic && m_size_dynamic>0) + constexpr maybe_static_array(DynVals ... vals) { + TDynamic values[m_size]{static_cast(vals)...}; + for(int r=0; r(static_val)); + } +#endif + } + } + + template + requires(N!=m_size_dynamic && m_size_dynamic>0) + constexpr maybe_static_array(const std::array& vals) { + for(int r=0; r(vals[r]); + } +#ifdef _MDSPAN_DEBUG + else { + assert(static_cast(vals[r])==static_cast(static_val)); + } +#endif + } + } + + template + requires(N!=m_size_dynamic && m_size_dynamic>0) + constexpr maybe_static_array(const std::span& vals) { + for(int r=0; r(vals[r]); + } +#ifdef _MDSPAN_DEBUG + else { + assert(static_cast(vals[r])==static_cast(static_val)); + } +#endif + } + } + + // access functions + constexpr static TStatic static_value(int r) { return static_vals_t::get(r); } + + constexpr TDynamic value(int r) const { + TStatic static_val = static_vals_t::get(r); + return static_val==dynamic_extent? + m_dyn_vals[dyn_map_t::get(r)] : static_cast(static_val); + } + constexpr TDynamic operator[](int r) const { + return value(r); + } + + // observers + constexpr static size_t size() { return m_size; } + constexpr static size_t size_dynamic() { return m_size_dynamic; } +}; + +#if 0 +template +struct maybe_static_array { + private: + using static_vals_t = static_array; + using dyn_map_t = index_sequence_scan_impl<0, size_t(Values==dyn_tag)...>; + constexpr static size_t m_size = sizeof...(Values); + constexpr static size_t m_size_dynamic = ((Values==dyn_tag) + ... + 0); + + + public: + + using value_type = TDynamic; + using static_value_type = TStatic; + constexpr static static_value_type tag_value = dyn_tag; + + constexpr static size_t size() { return 0; } + constexpr static size_t size_dynamic() { return 0; } +}; +#endif + +template +class extents { +public: + using rank_type = size_t; + using index_type = IndexType; + using size_type = make_unsigned_t; +private: + constexpr static rank_type m_rank = sizeof...(Extents); + constexpr static rank_type m_rank_dynamic = ((Extents==dynamic_extent) + ... + 0); + + using vals_t = maybe_static_array; + _MDSPAN_NO_UNIQUE_ADDRESS vals_t m_vals; +public: + constexpr static rank_type rank() { return m_rank; } + constexpr static rank_type rank_dynamic() { return m_rank_dynamic; } + + constexpr extents() = default; + + template + requires( + (is_convertible_v && ...) && + (is_nothrow_constructible_v && ...) && + (sizeof...(OtherIndexTypes)==m_rank || sizeof...(OtherIndexTypes)==m_rank_dynamic)) + constexpr extents(OtherIndexTypes ... dynvals):m_vals(static_cast(dynvals)...) {} + + template + requires( + is_convertible_v && + is_nothrow_constructible_v && + (N==m_rank || N==m_rank_dynamic)) + constexpr extents(const array& exts):m_vals(std::move(exts)) {} + + template + requires( + is_convertible_v && + is_nothrow_constructible_v && + (N==m_rank || N==m_rank_dynamic)) + constexpr extents(const span& exts):m_vals(std::move(exts)) {} + + template + requires((sizeof...(OtherExtents) == rank()) && + ((OtherExtents == dynamic_extent || + Extents == dynamic_extent || + OtherExtents == Extents) && ...)) + constexpr explicit((((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) + || ... ) || + (numeric_limits::max() < numeric_limits::max())) + extents(const extents& other) noexcept { + if constexpr(m_rank_dynamic>0) { + index_type vals[m_rank_dynamic]; + for(int r=0; r(vals)); + } + } + + constexpr index_type extent(int r) const { + return m_vals.value(r); + } + constexpr static size_t static_extent(int r) { + return vals_t::static_value(r); + } + + template + friend constexpr bool operator==(const extents& ext, + const extents& ext2) noexcept { + bool value = true; + for(int r=0; r> +struct __make_dextents; + +template +struct __make_dextents> { + using type = typename __make_dextents>::type; +}; + +template +struct __make_dextents> { + using type = ::std::experimental::extents; +}; + +} // end namespace detail + +template +using dextents = typename detail::__make_dextents::type; + +#if defined(_MDSPAN_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) +template +extents(IndexTypes...) + -> extents; +#endif + +namespace detail { + +template +struct __is_extents : ::std::false_type {}; + +template +struct __is_extents<::std::experimental::extents> : ::std::true_type {}; + +template +static constexpr bool __is_extents_v = __is_extents::value; + +} +} From b14a7501ea352908ba4a9eb1870eeba8dd4a67d8 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Mon, 21 Nov 2022 17:06:47 -0700 Subject: [PATCH 02/33] Add changes in layouts and mdspan to support new extents --- include/experimental/__p0009_bits/layout_left.hpp | 5 +++++ include/experimental/__p0009_bits/layout_right.hpp | 4 ++++ include/experimental/__p0009_bits/layout_stride.hpp | 8 ++++++++ include/experimental/__p0009_bits/mdspan.hpp | 11 +++++++++++ 4 files changed, 28 insertions(+) diff --git a/include/experimental/__p0009_bits/layout_left.hpp b/include/experimental/__p0009_bits/layout_left.hpp index a23a905c..f11879b6 100644 --- a/include/experimental/__p0009_bits/layout_left.hpp +++ b/include/experimental/__p0009_bits/layout_left.hpp @@ -47,8 +47,13 @@ class layout_left::mapping { _MDSPAN_HOST_DEVICE constexpr index_type __compute_offset( __rank_count, const I& i, Indices... idx) const { +#ifndef _MDSPAN_NEW_EXTENTS return __compute_offset(__rank_count(), idx...) * __extents.template __extent() + i; +#else + return __compute_offset(__rank_count(), idx...) * + __extents.extent(r) + i; +#endif } template diff --git a/include/experimental/__p0009_bits/layout_right.hpp b/include/experimental/__p0009_bits/layout_right.hpp index 634024af..1bb214d0 100644 --- a/include/experimental/__p0009_bits/layout_right.hpp +++ b/include/experimental/__p0009_bits/layout_right.hpp @@ -48,7 +48,11 @@ class layout_right::mapping { _MDSPAN_HOST_DEVICE constexpr index_type __compute_offset( index_type offset, __rank_count, const I& i, Indices... idx) const { +#ifndef _MDSPAN_NEW_EXTENTS return __compute_offset(offset * __extents.template __extent() + i,__rank_count(), idx...); +#else + return __compute_offset(offset * __extents.extent(r) + i,__rank_count(), idx...); +#endif } template diff --git a/include/experimental/__p0009_bits/layout_stride.hpp b/include/experimental/__p0009_bits/layout_stride.hpp index d53b5fe0..e15fed8b 100644 --- a/include/experimental/__p0009_bits/layout_stride.hpp +++ b/include/experimental/__p0009_bits/layout_stride.hpp @@ -189,12 +189,14 @@ struct layout_stride { } #endif +#ifndef _MDSPAN_NEW_EXTENTS 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())...}; } +#endif template MDSPAN_INLINE_FUNCTION @@ -221,6 +223,7 @@ struct layout_stride { #endif public: // but not really +#ifndef _MDSPAN_NEW_EXTENTS MDSPAN_INLINE_FUNCTION static constexpr mapping __make_mapping( @@ -242,6 +245,7 @@ struct layout_stride { #endif ); } +#endif //---------------------------------------------------------------------------- @@ -272,7 +276,11 @@ struct layout_stride { #else : __base_t(__base_t{__member_pair_t( #endif +#ifndef _MDSPAN_NEW_EXTENT2S e, __strides_storage_t(__impl::fill_strides(s)) +#else + e, __strides_storage_t(s) +#endif #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) } #else diff --git a/include/experimental/__p0009_bits/mdspan.hpp b/include/experimental/__p0009_bits/mdspan.hpp index 928ef631..a3b59742 100644 --- a/include/experimental/__p0009_bits/mdspan.hpp +++ b/include/experimental/__p0009_bits/mdspan.hpp @@ -43,6 +43,7 @@ class mdspan template struct __deduction_workaround> { +#ifndef _MDSPAN_NEW_EXTENTS 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)); @@ -51,6 +52,16 @@ class mdspan bool __empty(mdspan const& __self) noexcept { return (__self.rank()>0) && _MDSPAN_FOLD_OR((__self.__mapping_ref().extents().template __extent()==index_type(0))); } +#else + MDSPAN_FORCE_INLINE_FUNCTION static constexpr + size_t __size(mdspan const& __self) noexcept { + 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().extent(Idxs)==index_type(0))); + } +#endif template MDSPAN_FORCE_INLINE_FUNCTION static constexpr ReferenceType __callop(mdspan const& __self, const array& indices) noexcept { From c17c896a3f674feeba0264716903971d010836ac Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Mon, 21 Nov 2022 17:07:26 -0700 Subject: [PATCH 03/33] Enable new extents implementation --- include/experimental/__p0009_bits/extents.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index 6969337e..255a12e6 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -16,6 +16,9 @@ #pragma once #include "macros.hpp" +#if 1 +#include "extents2.hpp" +#else #include "static_array.hpp" #include "standard_layout_static_array.hpp" #include "trait_backports.hpp" // integer_sequence, etc. @@ -521,3 +524,4 @@ using __extents_to_partially_static_sizes_t = typename __extents_to_partially_st } // end namespace detail } // end namespace experimental } // end namespace std +#endif From f99b51c18bc77b263292c0aa14cea3db0a10886d Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Mon, 21 Nov 2022 17:07:52 -0700 Subject: [PATCH 04/33] Disable temporarly submdspan tests --- tests/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 61b663f1..c1df5175 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -66,3 +66,4 @@ if(NOT MDSPAN_ENABLE_CUDA AND NOT MDSPAN_ENABLE_HIP) mdspan_add_test(test_mdarray_ctors) mdspan_add_test(test_mdarray_to_mdspan) endif() +mdspan_add_test(test_mdspan_size) From f0ff77cb5ee53724d2bcbb88c2b64c2e9580cae4 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Fri, 23 Dec 2022 13:31:51 -0700 Subject: [PATCH 05/33] Fix a bunch of unsigned/signed warnings in new extents impl --- .../experimental/__p0009_bits/extents2.hpp | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/include/experimental/__p0009_bits/extents2.hpp b/include/experimental/__p0009_bits/extents2.hpp index 81403e37..628b1e5f 100644 --- a/include/experimental/__p0009_bits/extents2.hpp +++ b/include/experimental/__p0009_bits/extents2.hpp @@ -67,9 +67,9 @@ struct index_sequence_scan_impl; template struct index_sequence_scan_impl { - constexpr static size_t get(int r) { + constexpr static size_t get(size_t r) { if(r>R) return FirstVal + index_sequence_scan_impl::get(r); - else return 0; + else return 0; } template constexpr static size_t get() { return r>R? FirstVal + index_sequence_scan_impl::get(r):0; } @@ -77,13 +77,13 @@ struct index_sequence_scan_impl { template struct index_sequence_scan_impl { - constexpr static size_t get(int r) { return R>r?FirstVal:0; } + constexpr static size_t get(size_t r) { return R>r?FirstVal:0; } template constexpr static size_t get() { return R>r?FirstVal:0; } }; template<> struct index_sequence_scan_impl<0> { - constexpr static size_t get(int) { return 0; } + constexpr static size_t get(size_t) { return 0; } template constexpr static size_t get() { return 0; } }; @@ -93,14 +93,14 @@ struct index_sequence_scan_impl<0> { template struct possibly_empty_array { T vals[N]; - constexpr T& operator[] (int r) { return vals[r]; } - constexpr const T& operator[] (int r) const { return vals[r]; } + constexpr T& operator[] (size_t r) { return vals[r]; } + constexpr const T& operator[] (size_t r) const { return vals[r]; } }; template struct possibly_empty_array { - constexpr T operator[] (int) { return T(); } - constexpr const T operator[] (int) const { return T(); } + constexpr T operator[] (size_t) { return T(); } + constexpr const T operator[] (size_t) const { return T(); } }; @@ -127,7 +127,7 @@ struct maybe_static_array { requires(sizeof...(DynVals)==m_size_dynamic && m_size_dynamic>0) constexpr maybe_static_array(DynVals ... vals): m_dyn_vals{static_cast(vals)...} {} - + template requires(m_size_dynamic==0) constexpr maybe_static_array(DynVals ...): @@ -136,17 +136,17 @@ struct maybe_static_array { template requires(N==m_size_dynamic && N>0) constexpr maybe_static_array(const std::array& vals) { - for(int r=0; r(vals[r]); + for(size_t r=0; r(vals[r]); } template requires(N==m_size_dynamic && N==0) constexpr maybe_static_array(const std::array&) { } - + template requires(N==m_size_dynamic) constexpr maybe_static_array(const std::span& vals) { - for(int r=0; r(vals[r]); + for(size_t r=0; r(vals[r]); } // constructors from all values @@ -154,7 +154,7 @@ struct maybe_static_array { requires(sizeof...(DynVals)!=m_size_dynamic && m_size_dynamic>0) constexpr maybe_static_array(DynVals ... vals) { TDynamic values[m_size]{static_cast(vals)...}; - for(int r=0; r requires(N!=m_size_dynamic && m_size_dynamic>0) constexpr maybe_static_array(const std::array& vals) { - for(int r=0; r(vals[r]); @@ -186,7 +186,7 @@ struct maybe_static_array { template requires(N!=m_size_dynamic && m_size_dynamic>0) constexpr maybe_static_array(const std::span& vals) { - for(int r=0; r(vals[r]); @@ -246,7 +246,7 @@ class extents { private: constexpr static rank_type m_rank = sizeof...(Extents); constexpr static rank_type m_rank_dynamic = ((Extents==dynamic_extent) + ... + 0); - + using vals_t = maybe_static_array; _MDSPAN_NO_UNIQUE_ADDRESS vals_t m_vals; public: @@ -261,14 +261,14 @@ class extents { (is_nothrow_constructible_v && ...) && (sizeof...(OtherIndexTypes)==m_rank || sizeof...(OtherIndexTypes)==m_rank_dynamic)) constexpr extents(OtherIndexTypes ... dynvals):m_vals(static_cast(dynvals)...) {} - + template requires( is_convertible_v && is_nothrow_constructible_v && (N==m_rank || N==m_rank_dynamic)) constexpr extents(const array& exts):m_vals(std::move(exts)) {} - + template requires( is_convertible_v && @@ -277,17 +277,17 @@ class extents { constexpr extents(const span& exts):m_vals(std::move(exts)) {} template - requires((sizeof...(OtherExtents) == rank()) && - ((OtherExtents == dynamic_extent || - Extents == dynamic_extent || + requires((sizeof...(OtherExtents) == rank()) && + ((OtherExtents == dynamic_extent || + Extents == dynamic_extent || OtherExtents == Extents) && ...)) - constexpr explicit((((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) + constexpr explicit((((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) || (numeric_limits::max() < numeric_limits::max())) extents(const extents& other) noexcept { if constexpr(m_rank_dynamic>0) { index_type vals[m_rank_dynamic]; - for(int r=0; r& ext2) noexcept { bool value = true; - for(int r=0; r Date: Fri, 23 Dec 2022 13:47:46 -0700 Subject: [PATCH 06/33] Replace requires clause with C++14 backward macro --- .../experimental/__p0009_bits/extents2.hpp | 118 ++++++++++++------ 1 file changed, 82 insertions(+), 36 deletions(-) diff --git a/include/experimental/__p0009_bits/extents2.hpp b/include/experimental/__p0009_bits/extents2.hpp index 628b1e5f..5fcbff79 100644 --- a/include/experimental/__p0009_bits/extents2.hpp +++ b/include/experimental/__p0009_bits/extents2.hpp @@ -123,35 +123,60 @@ struct maybe_static_array { constexpr maybe_static_array() = default; // constructors from dynamic_extentamic values only - template - requires(sizeof...(DynVals)==m_size_dynamic && m_size_dynamic>0) + MDSPAN_TEMPLATE_REQUIRES( + class ... DynVals, + /* requires */( + sizeof...(DynVals)==m_size_dynamic && m_size_dynamic>0 + ) + ) constexpr maybe_static_array(DynVals ... vals): m_dyn_vals{static_cast(vals)...} {} - template - requires(m_size_dynamic==0) + MDSPAN_TEMPLATE_REQUIRES( + class ... DynVals, + /* requires */( + m_size_dynamic==0 + ) + ) constexpr maybe_static_array(DynVals ...): m_dyn_vals{} {} - template - requires(N==m_size_dynamic && N>0) + MDSPAN_TEMPLATE_REQUIRES( + class T, size_t N, + /* requires */( + N==m_size_dynamic && N>0 + ) + ) constexpr maybe_static_array(const std::array& vals) { for(size_t r=0; r(vals[r]); } - template - requires(N==m_size_dynamic && N==0) + + MDSPAN_TEMPLATE_REQUIRES( + class T, size_t N, + /* requires */( + N==m_size_dynamic && N==0 + ) + ) constexpr maybe_static_array(const std::array&) { } - template - requires(N==m_size_dynamic) + MDSPAN_TEMPLATE_REQUIRES( + class T, size_t N, + /* requires */( + N==m_size_dynamic + ) + ) constexpr maybe_static_array(const std::span& vals) { for(size_t r=0; r(vals[r]); } // constructors from all values - template - requires(sizeof...(DynVals)!=m_size_dynamic && m_size_dynamic>0) + MDSPAN_TEMPLATE_REQUIRES( + class ... DynVals, + /* requires */( + sizeof...(DynVals)!=m_size_dynamic && m_size_dynamic>0 + ) + ) constexpr maybe_static_array(DynVals ... vals) { TDynamic values[m_size]{static_cast(vals)...}; for(size_t r=0; r - requires(N!=m_size_dynamic && m_size_dynamic>0) + MDSPAN_TEMPLATE_REQUIRES( + class T, size_t N, + /* requires */( + N!=m_size_dynamic && m_size_dynamic>0 + ) + ) constexpr maybe_static_array(const std::array& vals) { for(size_t r=0; r - requires(N!=m_size_dynamic && m_size_dynamic>0) + MDSPAN_TEMPLATE_REQUIRES( + class T, size_t N, + /* requires */( + N!=m_size_dynamic && m_size_dynamic>0 + ) + ) constexpr maybe_static_array(const std::span& vals) { for(size_t r=0; r - requires( - (is_convertible_v && ...) && - (is_nothrow_constructible_v && ...) && - (sizeof...(OtherIndexTypes)==m_rank || sizeof...(OtherIndexTypes)==m_rank_dynamic)) + MDSPAN_TEMPLATE_REQUIRES( + class ... OtherIndexTypes, + /* requires */( + (is_convertible_v && ...) && + (is_nothrow_constructible_v && ...) && + (sizeof...(OtherIndexTypes)==m_rank || sizeof...(OtherIndexTypes)==m_rank_dynamic) + ) + ) constexpr extents(OtherIndexTypes ... dynvals):m_vals(static_cast(dynvals)...) {} - template - requires( - is_convertible_v && - is_nothrow_constructible_v && - (N==m_rank || N==m_rank_dynamic)) + MDSPAN_TEMPLATE_REQUIRES( + class OtherIndexType, size_t N, + /* requires */( + is_convertible_v && + is_nothrow_constructible_v && + (N==m_rank || N==m_rank_dynamic) + ) + ) constexpr extents(const array& exts):m_vals(std::move(exts)) {} - template - requires( - is_convertible_v && - is_nothrow_constructible_v && - (N==m_rank || N==m_rank_dynamic)) + MDSPAN_TEMPLATE_REQUIRES( + class OtherIndexType, size_t N, + /* requires */( + is_convertible_v && + is_nothrow_constructible_v && + (N==m_rank || N==m_rank_dynamic) + ) + ) constexpr extents(const span& exts):m_vals(std::move(exts)) {} - template - requires((sizeof...(OtherExtents) == rank()) && - ((OtherExtents == dynamic_extent || - Extents == dynamic_extent || - OtherExtents == Extents) && ...)) + MDSPAN_TEMPLATE_REQUIRES( + class OtherIndexType, size_t... OtherExtents, + /* requires */( + (sizeof...(OtherExtents) == rank()) && + ((OtherExtents == dynamic_extent || + Extents == dynamic_extent || + OtherExtents == Extents) && ...) + ) + ) constexpr explicit((((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) || (numeric_limits::max() < numeric_limits::max())) From 001a1617c21874ac195a03c090a4c7d2a3af3379 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Fri, 23 Dec 2022 13:53:38 -0700 Subject: [PATCH 07/33] Protect use of span in new extents impl --- include/experimental/__p0009_bits/extents2.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/experimental/__p0009_bits/extents2.hpp b/include/experimental/__p0009_bits/extents2.hpp index 5fcbff79..be828066 100644 --- a/include/experimental/__p0009_bits/extents2.hpp +++ b/include/experimental/__p0009_bits/extents2.hpp @@ -1,5 +1,9 @@ #include "dynamic_extent.hpp" + +#ifdef __cpp_lib_span #include "span" +#endif +#include "array" #define _MDSPAN_NEW_EXTENTS @@ -160,6 +164,7 @@ struct maybe_static_array { constexpr maybe_static_array(const std::array&) { } +#ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES( class T, size_t N, /* requires */( @@ -169,6 +174,7 @@ struct maybe_static_array { constexpr maybe_static_array(const std::span& vals) { for(size_t r=0; r(vals[r]); } +#endif // constructors from all values MDSPAN_TEMPLATE_REQUIRES( @@ -212,6 +218,7 @@ struct maybe_static_array { } } +#ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES( class T, size_t N, /* requires */( @@ -231,6 +238,7 @@ struct maybe_static_array { #endif } } +#endif // access functions constexpr static TStatic static_value(int r) { return static_vals_t::get(r); } @@ -308,6 +316,7 @@ class extents { ) constexpr extents(const array& exts):m_vals(std::move(exts)) {} +#ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES( class OtherIndexType, size_t N, /* requires */( @@ -317,6 +326,7 @@ class extents { ) ) constexpr extents(const span& exts):m_vals(std::move(exts)) {} +#endif MDSPAN_TEMPLATE_REQUIRES( class OtherIndexType, size_t... OtherExtents, From 3aa022b61a43908f173085a1583735697c937235 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Fri, 23 Dec 2022 14:44:10 -0700 Subject: [PATCH 08/33] Make new extents impl compile with C++14 --- .../experimental/__p0009_bits/extents2.hpp | 48 +++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/include/experimental/__p0009_bits/extents2.hpp b/include/experimental/__p0009_bits/extents2.hpp index be828066..fc2e8aae 100644 --- a/include/experimental/__p0009_bits/extents2.hpp +++ b/include/experimental/__p0009_bits/extents2.hpp @@ -21,8 +21,13 @@ struct static_array_impl { } template constexpr static T get() { +#if MDSPAN_HAS_CXX_17 if constexpr (r==R) return FirstExt; else return static_array_impl::template get(); +#else + if(r==R) return FirstExt; + else return static_array_impl::value(r); +#endif } }; @@ -114,7 +119,7 @@ struct maybe_static_array { private: using static_vals_t = static_array; constexpr static size_t m_size = sizeof...(Values); - constexpr static size_t m_size_dynamic = ((Values==dyn_tag) + ... + 0); + constexpr static size_t m_size_dynamic = _MDSPAN_FOLD_PLUS_RIGHT((Values==dyn_tag), 0); _MDSPAN_NO_UNIQUE_ADDRESS possibly_empty_array m_dyn_vals; public: @@ -139,7 +144,7 @@ struct maybe_static_array { MDSPAN_TEMPLATE_REQUIRES( class ... DynVals, /* requires */( - m_size_dynamic==0 + (m_size_dynamic==0) && (sizeof...(DynVals)>0) ) ) constexpr maybe_static_array(DynVals ...): @@ -184,6 +189,7 @@ struct maybe_static_array { ) ) constexpr maybe_static_array(DynVals ... vals) { + static_assert((sizeof...(DynVals)==m_size) || (m_size==dynamic_extent)); TDynamic values[m_size]{static_cast(vals)...}; for(size_t r=0; r& vals) { + static_assert((N==m_size) || (m_size==dynamic_extent)); +#ifdef _MDSPAN_DEBUG + assert(N==m_size); +#endif for(size_t r=0; r& vals) { + static_assert((N==m_size) || (m_size==dynamic_extent)); +#ifdef _MDSPAN_DEBUG + assert(N==m_size); +#endif for(size_t r=0; r; private: constexpr static rank_type m_rank = sizeof...(Extents); - constexpr static rank_type m_rank_dynamic = ((Extents==dynamic_extent) + ... + 0); + constexpr static rank_type m_rank_dynamic = _MDSPAN_FOLD_PLUS_RIGHT((Extents==dynamic_extent), /* + ... + */ 0); using vals_t = maybe_static_array; _MDSPAN_NO_UNIQUE_ADDRESS vals_t m_vals; @@ -299,8 +313,8 @@ class extents { MDSPAN_TEMPLATE_REQUIRES( class ... OtherIndexTypes, /* requires */( - (is_convertible_v && ...) && - (is_nothrow_constructible_v && ...) && + _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) ) ) @@ -309,8 +323,8 @@ class extents { MDSPAN_TEMPLATE_REQUIRES( class OtherIndexType, size_t N, /* requires */( - is_convertible_v && - is_nothrow_constructible_v && + _MDSPAN_TRAIT(is_convertible, OtherIndexType, index_type) && + _MDSPAN_TRAIT(is_nothrow_constructible, index_type, OtherIndexType) && (N==m_rank || N==m_rank_dynamic) ) ) @@ -320,8 +334,8 @@ class extents { MDSPAN_TEMPLATE_REQUIRES( class OtherIndexType, size_t N, /* requires */( - is_convertible_v && - is_nothrow_constructible_v && + _MDSPAN_TRAIT(is_convertible, OtherIndexType, index_type) && + _MDSPAN_TRAIT(is_nothrow_constructible, index_type, OtherIndexType) && (N==m_rank || N==m_rank_dynamic) ) ) @@ -332,23 +346,27 @@ class extents { class OtherIndexType, size_t... OtherExtents, /* requires */( (sizeof...(OtherExtents) == rank()) && - ((OtherExtents == dynamic_extent || + _MDSPAN_FOLD_AND((OtherExtents == dynamic_extent || Extents == dynamic_extent || - OtherExtents == Extents) && ...) + OtherExtents == Extents) /* && ... */) ) ) - constexpr explicit((((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) + MDSPAN_CONDITIONAL_EXPLICIT((((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) || (numeric_limits::max() < numeric_limits::max())) - extents(const extents& other) noexcept { + constexpr extents(const extents& other) noexcept { +#if MDSPAN_HAS_CXX_17 if constexpr(m_rank_dynamic>0) { - index_type vals[m_rank_dynamic]; +#else + if (m_rank_dynamic>0) { +#endif + std::array vals; for(size_type r=0; r(vals)); + m_vals = vals_t(std::move(vals)); } } From cd54023b1a1dc660baf48e2caa7bbb9a1d8678e7 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Fri, 23 Dec 2022 15:23:12 -0700 Subject: [PATCH 09/33] Add function markup to new extents implementation --- .../experimental/__p0009_bits/extents2.hpp | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/include/experimental/__p0009_bits/extents2.hpp b/include/experimental/__p0009_bits/extents2.hpp index fc2e8aae..d6159a9c 100644 --- a/include/experimental/__p0009_bits/extents2.hpp +++ b/include/experimental/__p0009_bits/extents2.hpp @@ -15,11 +15,13 @@ struct static_array_impl; template struct static_array_impl { + MDSPAN_INLINE_FUNCTION constexpr static T value(size_t r) { if(r==R) return FirstExt; else return static_array_impl::value(r); } template + MDSPAN_INLINE_FUNCTION constexpr static T get() { #if MDSPAN_HAS_CXX_17 if constexpr (r==R) return FirstExt; @@ -34,10 +36,12 @@ struct static_array_impl { // End the recursion template struct static_array_impl { + MDSPAN_INLINE_FUNCTION constexpr static T value(int) { return FirstExt; } template + MDSPAN_INLINE_FUNCTION constexpr static T get() { return FirstExt; } @@ -46,10 +50,12 @@ struct static_array_impl { // Don't start recursion if size 0 template struct static_array_impl<0, T> { + MDSPAN_INLINE_FUNCTION constexpr static T value(int) { return T(); } template + MDSPAN_INLINE_FUNCTION constexpr static T get() { return T(); } @@ -63,10 +69,14 @@ struct static_array { public: using value_type = T; + MDSPAN_INLINE_FUNCTION constexpr T operator[](int r) const { return get(r); } + MDSPAN_INLINE_FUNCTION constexpr static T get(int r) { return impl_t::value(r); } template + MDSPAN_INLINE_FUNCTION constexpr static T get() { return impl_t::template get(); } + MDSPAN_INLINE_FUNCTION constexpr static size_t size() { return sizeof...(Values); } }; @@ -76,24 +86,30 @@ 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 + MDSPAN_INLINE_FUNCTION constexpr static size_t get() { return r>R? FirstVal + index_sequence_scan_impl::get(r):0; } }; template struct index_sequence_scan_impl { + MDSPAN_INLINE_FUNCTION constexpr static size_t get(size_t r) { return R>r?FirstVal:0; } template + MDSPAN_INLINE_FUNCTION constexpr static size_t get() { return R>r?FirstVal:0; } }; template<> struct index_sequence_scan_impl<0> { + MDSPAN_INLINE_FUNCTION constexpr static size_t get(size_t) { return 0; } template + MDSPAN_INLINE_FUNCTION constexpr static size_t get() { return 0; } }; @@ -102,13 +118,17 @@ struct index_sequence_scan_impl<0> { template struct possibly_empty_array { T vals[N]; + MDSPAN_INLINE_FUNCTION constexpr T& operator[] (size_t r) { return vals[r]; } + MDSPAN_INLINE_FUNCTION constexpr const T& operator[] (size_t r) const { return vals[r]; } }; template struct possibly_empty_array { + MDSPAN_INLINE_FUNCTION constexpr T operator[] (size_t) { return T(); } + MDSPAN_INLINE_FUNCTION constexpr const T operator[] (size_t) const { return T(); } }; @@ -138,6 +158,7 @@ struct maybe_static_array { sizeof...(DynVals)==m_size_dynamic && m_size_dynamic>0 ) ) + MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(DynVals ... vals): m_dyn_vals{static_cast(vals)...} {} @@ -147,6 +168,7 @@ struct maybe_static_array { (m_size_dynamic==0) && (sizeof...(DynVals)>0) ) ) + MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(DynVals ...): m_dyn_vals{} {} @@ -156,6 +178,7 @@ struct maybe_static_array { N==m_size_dynamic && N>0 ) ) + MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(const std::array& vals) { for(size_t r=0; r(vals[r]); } @@ -166,6 +189,7 @@ struct maybe_static_array { N==m_size_dynamic && N==0 ) ) + MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(const std::array&) { } @@ -176,6 +200,7 @@ struct maybe_static_array { N==m_size_dynamic ) ) + MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(const std::span& vals) { for(size_t r=0; r(vals[r]); } @@ -188,6 +213,7 @@ struct maybe_static_array { sizeof...(DynVals)!=m_size_dynamic && m_size_dynamic>0 ) ) + MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(DynVals ... vals) { static_assert((sizeof...(DynVals)==m_size) || (m_size==dynamic_extent)); TDynamic values[m_size]{static_cast(vals)...}; @@ -210,6 +236,7 @@ struct maybe_static_array { N!=m_size_dynamic && m_size_dynamic>0 ) ) + MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(const std::array& vals) { static_assert((N==m_size) || (m_size==dynamic_extent)); #ifdef _MDSPAN_DEBUG @@ -235,6 +262,7 @@ struct maybe_static_array { N!=m_size_dynamic && m_size_dynamic>0 ) ) + MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(const std::span& vals) { static_assert((N==m_size) || (m_size==dynamic_extent)); #ifdef _MDSPAN_DEBUG @@ -255,19 +283,24 @@ struct maybe_static_array { #endif // access functions + MDSPAN_INLINE_FUNCTION constexpr static TStatic static_value(int r) { return static_vals_t::get(r); } + MDSPAN_INLINE_FUNCTION constexpr TDynamic value(int r) const { TStatic static_val = static_vals_t::get(r); return static_val==dynamic_extent? m_dyn_vals[dyn_map_t::get(r)] : static_cast(static_val); } + MDSPAN_INLINE_FUNCTION constexpr TDynamic operator[](int r) const { return value(r); } // observers + MDSPAN_INLINE_FUNCTION constexpr static size_t size() { return m_size; } + MDSPAN_INLINE_FUNCTION constexpr static size_t size_dynamic() { return m_size_dynamic; } }; @@ -305,9 +338,12 @@ class extents { using vals_t = maybe_static_array; _MDSPAN_NO_UNIQUE_ADDRESS vals_t m_vals; public: + MDSPAN_INLINE_FUNCTION constexpr static rank_type rank() { return m_rank; } + MDSPAN_INLINE_FUNCTION constexpr static rank_type rank_dynamic() { return m_rank_dynamic; } + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents() = default; MDSPAN_TEMPLATE_REQUIRES( @@ -318,6 +354,7 @@ class extents { (sizeof...(OtherIndexTypes)==m_rank || sizeof...(OtherIndexTypes)==m_rank_dynamic) ) ) + MDSPAN_INLINE_FUNCTION constexpr extents(OtherIndexTypes ... dynvals):m_vals(static_cast(dynvals)...) {} MDSPAN_TEMPLATE_REQUIRES( @@ -328,6 +365,7 @@ class extents { (N==m_rank || N==m_rank_dynamic) ) ) + MDSPAN_INLINE_FUNCTION constexpr extents(const array& exts):m_vals(std::move(exts)) {} #ifdef __cpp_lib_span @@ -339,6 +377,7 @@ class extents { (N==m_rank || N==m_rank_dynamic) ) ) + MDSPAN_INLINE_FUNCTION constexpr extents(const span& exts):m_vals(std::move(exts)) {} #endif @@ -354,6 +393,7 @@ class extents { MDSPAN_CONDITIONAL_EXPLICIT((((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) || (numeric_limits::max() < numeric_limits::max())) + MDSPAN_INLINE_FUNCTION constexpr extents(const extents& other) noexcept { #if MDSPAN_HAS_CXX_17 if constexpr(m_rank_dynamic>0) { @@ -370,14 +410,17 @@ class extents { } } + MDSPAN_INLINE_FUNCTION constexpr index_type extent(rank_type r) const { return m_vals.value(r); } + MDSPAN_INLINE_FUNCTION constexpr static size_t static_extent(rank_type r) { return vals_t::static_value(r); } template + MDSPAN_INLINE_FUNCTION friend constexpr bool operator==(const extents& ext, const extents& ext2) noexcept { bool value = true; From 15e622475c1d7f197cc87f7428b97030d0e13d01 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Wed, 1 Feb 2023 14:28:34 -0700 Subject: [PATCH 10/33] Get new extents to work with nvcc --- compilation_tests/ctest_no_unique_address.cpp | 2 + .../experimental/__p0009_bits/extents2.hpp | 161 ++++++++++++++---- tests/CMakeLists.txt | 1 - 3 files changed, 127 insertions(+), 37 deletions(-) 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/include/experimental/__p0009_bits/extents2.hpp b/include/experimental/__p0009_bits/extents2.hpp index d6159a9c..4551c2ee 100644 --- a/include/experimental/__p0009_bits/extents2.hpp +++ b/include/experimental/__p0009_bits/extents2.hpp @@ -7,7 +7,32 @@ #define _MDSPAN_NEW_EXTENTS -namespace std::experimental { +namespace std { +namespace experimental { +namespace detail { + +// Function used to check compatibility of extents in converting constructor +// can't be private member functions for some reason + template + static constexpr std::integral_constant __check_compatible_extents( + std::integral_constant, std::integer_sequence, std::integer_sequence + ) noexcept { return { }; } + + template + static constexpr std::integral_constant< + bool, + _MDSPAN_FOLD_AND( + ( + Extents == dynamic_extent + || OtherExtents == dynamic_extent + || Extents == OtherExtents + ) /* && ... */ + ) + > + __check_compatible_extents( + std::integral_constant, std::integer_sequence, std::integer_sequence + ) noexcept { return { }; } + // Implementation of Static Array, recursive implementation of get template @@ -98,8 +123,14 @@ struct index_sequence_scan_impl { template struct index_sequence_scan_impl { +#ifdef __NVCC__ + // 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; } +#else MDSPAN_INLINE_FUNCTION constexpr static size_t get(size_t r) { return R>r?FirstVal:0; } +#endif template MDSPAN_INLINE_FUNCTION constexpr static size_t get() { return R>r?FirstVal:0; } @@ -215,7 +246,7 @@ struct maybe_static_array { ) MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(DynVals ... vals) { - static_assert((sizeof...(DynVals)==m_size) || (m_size==dynamic_extent)); + static_assert((sizeof...(DynVals)==m_size), "Invalid number of values."); TDynamic values[m_size]{static_cast(vals)...}; for(size_t r=0; r& vals) { - static_assert((N==m_size) || (m_size==dynamic_extent)); + static_assert((N==m_size), "Invalid number of values."); #ifdef _MDSPAN_DEBUG assert(N==m_size); #endif @@ -325,6 +356,11 @@ struct maybe_static_array { }; #endif +}}} // namespace std::experimental::detail + +namespace std { +namespace experimental { + template class extents { public: @@ -335,14 +371,24 @@ class extents { constexpr static rank_type m_rank = sizeof...(Extents); constexpr static rank_type m_rank_dynamic = _MDSPAN_FOLD_PLUS_RIGHT((Extents==dynamic_extent), /* + ... + */ 0); - using vals_t = maybe_static_array; + using vals_t = detail::maybe_static_array; _MDSPAN_NO_UNIQUE_ADDRESS vals_t m_vals; + public: MDSPAN_INLINE_FUNCTION constexpr static rank_type rank() { return m_rank; } MDSPAN_INLINE_FUNCTION constexpr static rank_type rank_dynamic() { return m_rank_dynamic; } + MDSPAN_INLINE_FUNCTION + constexpr index_type extent(rank_type r) const { + return m_vals.value(r); + } + MDSPAN_INLINE_FUNCTION + constexpr static size_t static_extent(rank_type r) { + return vals_t::static_value(r); + } + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents() = default; @@ -360,8 +406,8 @@ class extents { MDSPAN_TEMPLATE_REQUIRES( class OtherIndexType, size_t N, /* requires */( - _MDSPAN_TRAIT(is_convertible, OtherIndexType, index_type) && - _MDSPAN_TRAIT(is_nothrow_constructible, index_type, OtherIndexType) && + // _MDSPAN_TRAIT(is_convertible, OtherIndexType, index_type) && + // _MDSPAN_TRAIT(is_nothrow_constructible, index_type, OtherIndexType) && (N==m_rank || N==m_rank_dynamic) ) ) @@ -381,52 +427,95 @@ class extents { constexpr extents(const span& exts):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( - class OtherIndexType, size_t... OtherExtents, + size_t DynCount, size_t R, class OtherExtents, class ... DynamicValues, /* requires */( - (sizeof...(OtherExtents) == rank()) && - _MDSPAN_FOLD_AND((OtherExtents == dynamic_extent || - Extents == dynamic_extent || - OtherExtents == Extents) /* && ... */) + (R < m_rank) && + (static_extent(R) == dynamic_extent) ) ) - MDSPAN_CONDITIONAL_EXPLICIT((((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) - || ... ) || - (numeric_limits::max() < numeric_limits::max())) MDSPAN_INLINE_FUNCTION - constexpr extents(const extents& other) noexcept { -#if MDSPAN_HAS_CXX_17 - if constexpr(m_rank_dynamic>0) { -#else - if (m_rank_dynamic>0) { -#endif - std::array vals; - for(size_type r=0; r, + std::integral_constant, + const OtherExtents& exts, DynamicValues ... dynamic_values) { + return __construct_vals_from_extents(std::integral_constant(), + std::integral_constant(), + exts, dynamic_values ..., exts.extent(R)); } + 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 - constexpr index_type extent(rank_type r) const { - return m_vals.value(r); + vals_t __construct_vals_from_extents(std::integral_constant, + std::integral_constant, + const OtherExtents& exts, DynamicValues ... dynamic_values) { + return __construct_vals_from_extents(std::integral_constant(), + std::integral_constant(), + exts, dynamic_values ...); } + + MDSPAN_TEMPLATE_REQUIRES( + size_t DynCount, size_t R, class OtherExtents, class ... DynamicValues, + /* requires */ ( + (R == m_rank) && + (DynCount == m_rank_dynamic) + ) + ) MDSPAN_INLINE_FUNCTION - constexpr static size_t static_extent(rank_type r) { - return vals_t::static_value(r); + vals_t __construct_vals_from_extents(std::integral_constant, + std::integral_constant, + const OtherExtents&, DynamicValues ... dynamic_values) { + return vals_t{static_cast(dynamic_values)...}; } +public: + 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): + m_vals(__construct_vals_from_extents(std::integral_constant(), + std::integral_constant(), + other)) {} + template MDSPAN_INLINE_FUNCTION - friend constexpr bool operator==(const extents& ext, - const extents& ext2) noexcept { + friend constexpr bool operator==(const extents& lhs, + const extents& rhs) noexcept { bool value = true; - for(size_type r=0; r + MDSPAN_INLINE_FUNCTION + friend constexpr bool operator!=(extents const& lhs, extents const& rhs) noexcept { + return !(lhs == rhs); + } +#endif }; namespace detail { @@ -468,4 +557,4 @@ template static constexpr bool __is_extents_v = __is_extents::value; } -} +}} // namespace std::experimental diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c1df5175..61b663f1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -66,4 +66,3 @@ if(NOT MDSPAN_ENABLE_CUDA AND NOT MDSPAN_ENABLE_HIP) mdspan_add_test(test_mdarray_ctors) mdspan_add_test(test_mdarray_to_mdspan) endif() -mdspan_add_test(test_mdspan_size) From 6e93f6fda9c33002fddf4a6cc3541e7b0eb99dfd Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Wed, 1 Feb 2023 15:41:38 -0700 Subject: [PATCH 11/33] Fix a bit more stuff for NVCC build --- include/experimental/__p0009_bits/extents2.hpp | 2 +- include/experimental/__p0009_bits/mdspan.hpp | 2 +- tests/foo_customizations.hpp | 3 ++- tests/test_mdspan_swap.cpp | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/experimental/__p0009_bits/extents2.hpp b/include/experimental/__p0009_bits/extents2.hpp index 4551c2ee..0741e7fb 100644 --- a/include/experimental/__p0009_bits/extents2.hpp +++ b/include/experimental/__p0009_bits/extents2.hpp @@ -123,7 +123,7 @@ struct index_sequence_scan_impl { template struct index_sequence_scan_impl { -#ifdef __NVCC__ +#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; } diff --git a/include/experimental/__p0009_bits/mdspan.hpp b/include/experimental/__p0009_bits/mdspan.hpp index a3b59742..822912d6 100644 --- a/include/experimental/__p0009_bits/mdspan.hpp +++ b/include/experimental/__p0009_bits/mdspan.hpp @@ -333,7 +333,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/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; From e873312929e9e1e54debab99c6bf7e97412bcf8d Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Wed, 1 Feb 2023 15:42:13 -0700 Subject: [PATCH 12/33] Clang-format --- .../experimental/__p0009_bits/extents2.hpp | 623 +++++++++--------- 1 file changed, 303 insertions(+), 320 deletions(-) diff --git a/include/experimental/__p0009_bits/extents2.hpp b/include/experimental/__p0009_bits/extents2.hpp index 0741e7fb..2118e9a4 100644 --- a/include/experimental/__p0009_bits/extents2.hpp +++ b/include/experimental/__p0009_bits/extents2.hpp @@ -1,3 +1,4 @@ +#pragma once #include "dynamic_extent.hpp" #ifdef __cpp_lib_span @@ -13,84 +14,78 @@ namespace detail { // Function used to check compatibility of extents in converting constructor // can't be private member functions for some reason - template - static constexpr std::integral_constant __check_compatible_extents( - std::integral_constant, std::integer_sequence, std::integer_sequence - ) noexcept { return { }; } - - template - static constexpr std::integral_constant< - bool, - _MDSPAN_FOLD_AND( - ( - Extents == dynamic_extent - || OtherExtents == dynamic_extent - || Extents == OtherExtents - ) /* && ... */ - ) - > - __check_compatible_extents( - std::integral_constant, std::integer_sequence, std::integer_sequence - ) noexcept { return { }; } +template +static constexpr std::integral_constant __check_compatible_extents( + std::integral_constant, + std::integer_sequence, + std::integer_sequence) noexcept { + return {}; +} +template +static constexpr std::integral_constant< + bool, _MDSPAN_FOLD_AND((Extents == dynamic_extent || + OtherExtents == dynamic_extent || + Extents == OtherExtents) /* && ... */ + )> +__check_compatible_extents( + std::integral_constant, + std::integer_sequence, + std::integer_sequence) noexcept { + return {}; +} // Implementation of Static Array, recursive implementation of get -template -struct static_array_impl; +template struct static_array_impl; -template +template struct static_array_impl { MDSPAN_INLINE_FUNCTION constexpr static T value(size_t r) { - if(r==R) return FirstExt; - else return static_array_impl::value(r); + if (r == R) + return FirstExt; + else + return static_array_impl::value(r); } - template - MDSPAN_INLINE_FUNCTION - constexpr static T get() { + 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(); + if constexpr (r == R) + return FirstExt; + else + return static_array_impl::template get(); #else - if(r==R) return FirstExt; - else return static_array_impl::value(r); + if (r == R) + return FirstExt; + else + return static_array_impl::value(r); #endif } }; // End the recursion -template +template struct static_array_impl { MDSPAN_INLINE_FUNCTION - constexpr static T value(int) { - return FirstExt; - } - template - MDSPAN_INLINE_FUNCTION - constexpr static T get() { + constexpr static T value(int) { 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> { +template struct static_array_impl<0, T> { MDSPAN_INLINE_FUNCTION - constexpr static T value(int) { - return T(); - } - template - MDSPAN_INLINE_FUNCTION - constexpr static T get() { + constexpr static T value(int) { 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 { +template struct static_array { private: using impl_t = static_array_impl<0, T, Values...>; + public: using value_type = T; @@ -98,241 +93,222 @@ struct static_array { constexpr T operator[](int r) const { return get(r); } MDSPAN_INLINE_FUNCTION constexpr static T get(int r) { return impl_t::value(r); } - template - MDSPAN_INLINE_FUNCTION - constexpr static T get() { return impl_t::template get(); } + template MDSPAN_INLINE_FUNCTION constexpr static T get() { + return impl_t::template get(); + } MDSPAN_INLINE_FUNCTION constexpr static size_t size() { return sizeof...(Values); } }; -// index_sequence_scan takes indicies and provides get(r) and get() to get the sum of the first r-1 values -template -struct index_sequence_scan_impl; +// index_sequence_scan takes indicies and provides get(r) and get() to get +// the sum of the first r-1 values +template struct index_sequence_scan_impl; -template +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; + if (r > R) + return FirstVal + index_sequence_scan_impl::get(r); + else + return 0; + } + template MDSPAN_INLINE_FUNCTION constexpr static size_t get() { + return r > R ? FirstVal + index_sequence_scan_impl::get(r) + : 0; } - template - MDSPAN_INLINE_FUNCTION - constexpr static size_t get() { return r>R? FirstVal + index_sequence_scan_impl::get(r):0; } }; -template +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 + // 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; } + constexpr static size_t get(size_t r) { + return static_cast(R) > static_cast(r) ? FirstVal : 0; + } #else MDSPAN_INLINE_FUNCTION - constexpr static size_t get(size_t r) { return R>r?FirstVal:0; } + constexpr static size_t get(size_t r) { return R > r ? FirstVal : 0; } #endif - template - MDSPAN_INLINE_FUNCTION - constexpr static size_t get() { return R>r?FirstVal:0; } + template MDSPAN_INLINE_FUNCTION constexpr static size_t get() { + return R > r ? FirstVal : 0; + } }; -template<> -struct index_sequence_scan_impl<0> { +template <> struct index_sequence_scan_impl<0> { MDSPAN_INLINE_FUNCTION constexpr static size_t get(size_t) { return 0; } - template - MDSPAN_INLINE_FUNCTION - constexpr static size_t get() { return 0; } + template MDSPAN_INLINE_FUNCTION constexpr static size_t get() { + return 0; + } }; -// Need this to have fully empty class maybe_static_array with all entries static -// Rather specialize this small helper class on size 0, then the whole thing -template -struct possibly_empty_array { +// Need this to have fully empty class maybe_static_array with all entries +// static Rather specialize this small helper class on size 0, then the whole +// thing +template struct possibly_empty_array { T vals[N]; MDSPAN_INLINE_FUNCTION - constexpr T& operator[] (size_t r) { return vals[r]; } + constexpr T &operator[](size_t r) { return vals[r]; } MDSPAN_INLINE_FUNCTION - constexpr const T& operator[] (size_t r) const { return vals[r]; } + constexpr const T &operator[](size_t r) const { return vals[r]; } }; -template -struct possibly_empty_array { +template struct possibly_empty_array { MDSPAN_INLINE_FUNCTION - constexpr T operator[] (size_t) { return T(); } + constexpr T operator[](size_t) { return T(); } MDSPAN_INLINE_FUNCTION - constexpr const T operator[] (size_t) const { return T(); } + constexpr const T operator[](size_t) const { return T(); } }; - // maybe_static_array is an array which has a mix of static and dynamic values -template +template struct maybe_static_array { - private: - 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); +private: + 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); - _MDSPAN_NO_UNIQUE_ADDRESS possibly_empty_array m_dyn_vals; - public: - using dyn_map_t = index_sequence_scan_impl<0, size_t(Values==dyn_tag)...>; + _MDSPAN_NO_UNIQUE_ADDRESS possibly_empty_array + m_dyn_vals; - using value_type = TDynamic; - using static_value_type = TStatic; - constexpr static static_value_type tag_value = dyn_tag; +public: + using dyn_map_t = index_sequence_scan_impl<0, size_t(Values == dyn_tag)...>; - constexpr maybe_static_array() = default; - - // constructors from dynamic_extentamic 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)...} {} - - MDSPAN_TEMPLATE_REQUIRES( - class ... DynVals, - /* requires */( - (m_size_dynamic==0) && (sizeof...(DynVals)>0) - ) - ) - MDSPAN_INLINE_FUNCTION - constexpr maybe_static_array(DynVals ...): - m_dyn_vals{} {} - - 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(vals[r]); - } + using value_type = TDynamic; + using static_value_type = TStatic; + constexpr static static_value_type tag_value = dyn_tag; - 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&) { - } + constexpr maybe_static_array() = default; + + // constructors from dynamic_extentamic 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)...} {} + + MDSPAN_TEMPLATE_REQUIRES(class... DynVals, + /* requires */ ((m_size_dynamic == 0) && + (sizeof...(DynVals) > 0))) + MDSPAN_INLINE_FUNCTION + constexpr maybe_static_array(DynVals...) : m_dyn_vals{} {} + + 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]); + } + + 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 &) {} #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(vals[r]); - } + 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 - // 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 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 == dynamic_extent) { + m_dyn_vals[dyn_map_t::get(r)] = values[r]; + } #ifdef _MDSPAN_DEBUG - else { - assert(values[r]==static_cast(static_val)); - } -#endif + else { + assert(values[r] == static_cast(static_val)); } +#endif } + } - MDSPAN_TEMPLATE_REQUIRES( + MDSPAN_TEMPLATE_REQUIRES( class T, size_t N, - /* requires */( - N!=m_size_dynamic && m_size_dynamic>0 - ) - ) - MDSPAN_INLINE_FUNCTION - constexpr maybe_static_array(const std::array& vals) { - static_assert((N==m_size), "Invalid number of values."); + /* requires */ (N != m_size_dynamic && m_size_dynamic > 0)) + MDSPAN_INLINE_FUNCTION + constexpr maybe_static_array(const std::array &vals) { + static_assert((N == m_size), "Invalid number of values."); #ifdef _MDSPAN_DEBUG - assert(N==m_size); + assert(N == m_size); #endif - for(size_t r=0; r(vals[r]); - } + for (size_t r = 0; r < m_size; r++) { + TStatic static_val = static_vals_t::get(r); + if (static_val == dynamic_extent) { + 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)); - } -#endif + else { + assert(static_cast(vals[r]) == + static_cast(static_val)); } +#endif } + } #ifdef __cpp_lib_span - MDSPAN_TEMPLATE_REQUIRES( + MDSPAN_TEMPLATE_REQUIRES( class T, size_t N, - /* requires */( - N!=m_size_dynamic && m_size_dynamic>0 - ) - ) - MDSPAN_INLINE_FUNCTION - constexpr maybe_static_array(const std::span& vals) { - static_assert((N==m_size) || (m_size==dynamic_extent)); + /* requires */ (N != m_size_dynamic && m_size_dynamic > 0)) + MDSPAN_INLINE_FUNCTION + constexpr maybe_static_array(const std::span &vals) { + static_assert((N == m_size) || (m_size == dynamic_extent)); #ifdef _MDSPAN_DEBUG - assert(N==m_size); + assert(N == m_size); #endif - for(size_t r=0; r(vals[r]); - } + for (size_t r = 0; r < m_size; r++) { + TStatic static_val = static_vals_t::get(r); + if (static_val == dynamic_extent) { + 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)); - } -#endif + else { + assert(static_cast(vals[r]) == + static_cast(static_val)); } +#endif } + } #endif - // access functions - MDSPAN_INLINE_FUNCTION - constexpr static TStatic static_value(int r) { return static_vals_t::get(r); } + // access functions + MDSPAN_INLINE_FUNCTION + constexpr static TStatic static_value(int r) { return static_vals_t::get(r); } - MDSPAN_INLINE_FUNCTION - constexpr TDynamic value(int r) const { - TStatic static_val = static_vals_t::get(r); - return static_val==dynamic_extent? - m_dyn_vals[dyn_map_t::get(r)] : static_cast(static_val); - } - MDSPAN_INLINE_FUNCTION - constexpr TDynamic operator[](int r) const { - return value(r); - } + MDSPAN_INLINE_FUNCTION + constexpr TDynamic value(int r) const { + TStatic static_val = static_vals_t::get(r); + return static_val == dynamic_extent ? m_dyn_vals[dyn_map_t::get(r)] + : static_cast(static_val); + } + MDSPAN_INLINE_FUNCTION + constexpr TDynamic operator[](int r) const { return value(r); } - // observers - MDSPAN_INLINE_FUNCTION - constexpr static size_t size() { return m_size; } - MDSPAN_INLINE_FUNCTION - constexpr static size_t size_dynamic() { return m_size_dynamic; } + // observers + MDSPAN_INLINE_FUNCTION + constexpr static size_t size() { return m_size; } + MDSPAN_INLINE_FUNCTION + constexpr static size_t size_dynamic() { return m_size_dynamic; } }; #if 0 @@ -356,22 +332,26 @@ struct maybe_static_array { }; #endif -}}} // namespace std::experimental::detail +} // namespace detail +} // namespace experimental +} // namespace std namespace std { namespace experimental { -template -class extents { +template class extents { public: using rank_type = size_t; using index_type = IndexType; using size_type = make_unsigned_t; + private: constexpr static rank_type m_rank = sizeof...(Extents); - constexpr static rank_type m_rank_dynamic = _MDSPAN_FOLD_PLUS_RIGHT((Extents==dynamic_extent), /* + ... + */ 0); + constexpr static rank_type m_rank_dynamic = + _MDSPAN_FOLD_PLUS_RIGHT((Extents == dynamic_extent), /* + ... + */ 0); - using vals_t = detail::maybe_static_array; + using vals_t = + detail::maybe_static_array; _MDSPAN_NO_UNIQUE_ADDRESS vals_t m_vals; public: @@ -381,9 +361,7 @@ class extents { constexpr static rank_type rank_dynamic() { return m_rank_dynamic; } MDSPAN_INLINE_FUNCTION - constexpr index_type extent(rank_type r) const { - return m_vals.value(r); - } + constexpr index_type extent(rank_type r) const { return m_vals.value(r); } MDSPAN_INLINE_FUNCTION constexpr static size_t static_extent(rank_type r) { return vals_t::static_value(r); @@ -393,126 +371,123 @@ class extents { constexpr extents() = default; 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 extents(OtherIndexTypes ... dynvals):m_vals(static_cast(dynvals)...) {} + 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 extents(OtherIndexTypes... dynvals) + : m_vals(static_cast(dynvals)...) {} 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) - ) - ) + 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 - constexpr extents(const array& exts):m_vals(std::move(exts)) {} + constexpr extents(const array &exts) + : 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 - constexpr extents(const span& exts):m_vals(std::move(exts)) {} + 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 + constexpr extents(const span &exts) + : 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) - ) - ) + 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) { - return __construct_vals_from_extents(std::integral_constant(), - std::integral_constant(), - exts, dynamic_values ..., exts.extent(R)); + const OtherExtents &exts, + DynamicValues... dynamic_values) { + return __construct_vals_from_extents( + std::integral_constant(), + std::integral_constant(), exts, dynamic_values..., + exts.extent(R)); } MDSPAN_TEMPLATE_REQUIRES( - size_t DynCount, size_t R, class OtherExtents, class ... DynamicValues, - /* requires */( - (R < m_rank) && - (static_extent(R) != dynamic_extent) - ) - ) + 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) { - return __construct_vals_from_extents(std::integral_constant(), - std::integral_constant(), - exts, dynamic_values ...); + const OtherExtents &exts, + DynamicValues... dynamic_values) { + return __construct_vals_from_extents( + std::integral_constant(), + std::integral_constant(), exts, dynamic_values...); } MDSPAN_TEMPLATE_REQUIRES( - size_t DynCount, size_t R, class OtherExtents, class ... DynamicValues, - /* requires */ ( - (R == m_rank) && - (DynCount == m_rank_dynamic) - ) - ) + size_t DynCount, size_t R, class OtherExtents, class... DynamicValues, + /* requires */ ((R == m_rank) && (DynCount == m_rank_dynamic))) MDSPAN_INLINE_FUNCTION vals_t __construct_vals_from_extents(std::integral_constant, std::integral_constant, - const OtherExtents&, DynamicValues ... dynamic_values) { + const OtherExtents &, + DynamicValues... dynamic_values) { return vals_t{static_cast(dynamic_values)...}; } public: 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): - m_vals(__construct_vals_from_extents(std::integral_constant(), - std::integral_constant(), - other)) {} - - template - MDSPAN_INLINE_FUNCTION - friend constexpr bool operator==(const extents& lhs, - const extents& rhs) noexcept { + 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) + : m_vals(__construct_vals_from_extents( + std::integral_constant(), + std::integral_constant(), other)) {} + + template + MDSPAN_INLINE_FUNCTION friend constexpr bool + operator==(const extents &lhs, + const extents &rhs) noexcept { bool value = true; - for(size_type r=0; r - MDSPAN_INLINE_FUNCTION - friend constexpr bool operator!=(extents const& lhs, extents const& rhs) noexcept { + template + MDSPAN_INLINE_FUNCTION friend constexpr bool + operator!=(extents const &lhs, + extents const &rhs) noexcept { return !(lhs == rhs); } #endif @@ -520,17 +495,23 @@ class 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; }; @@ -542,19 +523,21 @@ using dextents = typename detail::__make_dextents::type; #if defined(_MDSPAN_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) template extents(IndexTypes...) - -> extents; + -> extents; #endif 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; -} -}} // namespace std::experimental +} // namespace detail +} // namespace experimental +} // namespace std From 65d550e6eedd152c77e4f83e17878cd03723f8c2 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Wed, 15 Mar 2023 13:20:02 -0600 Subject: [PATCH 13/33] Delete old extents --- include/experimental/__p0009_bits/extents.hpp | 527 ------------------ 1 file changed, 527 deletions(-) delete mode 100644 include/experimental/__p0009_bits/extents.hpp diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp deleted file mode 100644 index 255a12e6..00000000 --- a/include/experimental/__p0009_bits/extents.hpp +++ /dev/null @@ -1,527 +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" -#if 1 -#include "extents2.hpp" -#else -#include "static_array.hpp" -#include "standard_layout_static_array.hpp" -#include "trait_backports.hpp" // integer_sequence, etc. - -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) -# include "no_unique_address.hpp" -#endif - -#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; -}; - -template -static constexpr std::false_type _check_compatible_extents( - std::false_type, std::integer_sequence, std::integer_sequence -) noexcept { return { }; } - -// This helper prevents ICE's on MSVC. -template -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 { }; - -} // end namespace detail - -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 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; - -// 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 - -// private members dealing with the way we internally store dynamic extents - private: - - 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 - } - 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(); -#endif - } - - 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); - } - - template - friend class extents; - - template - MDSPAN_INLINE_FUNCTION - constexpr bool _eq_impl(std::experimental::extents, false_type, index_sequence) const noexcept { return false; } - template - 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()) /* && ... */ - ); - } - - template - MDSPAN_INLINE_FUNCTION - constexpr bool _not_eq_impl(std::experimental::extents, false_type, index_sequence) const noexcept { return true; } - template - 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()) /* || ... */ - ); - } - -#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - MDSPAN_INLINE_FUNCTION constexpr explicit - extents(__base_t&& __b) noexcept - : __base_t(::std::move(__b)) - { } -#endif - - -// public interface: -public: - /* Defined above for use in the private code - using rank_type = size_t; - using index_type = ThisIndexType; - */ - - 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); } - - //-------------------------------------------------------------------------------- - // Constructors, Destructors, and Assignment - - // 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 - */ - } - -#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_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{ -#endif - std::conditional_t(), - static_cast(exts)... -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#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()) - 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{ -#endif - std::conditional_t, - detail::__construct_psa_from_all_exts_array_tag_t>(), - std::array{exts} -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#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()) - 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{ -#endif - std::conditional_t, - detail::__construct_psa_from_all_exts_array_tag_t>(), - exts -#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - } -#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 - 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 - { } - - //-------------------------------------------------------------------------------- - - 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{}); - } - - 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 - 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{} - ); - } - -#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{} - ); - } -#endif - - // End of public interface - -public: // (but not really) - - 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) - } -#endif - ); - } - - template - MDSPAN_FORCE_INLINE_FUNCTION - constexpr - index_type __extent() const noexcept { - return __storage().template __get_n(); - } - - template - MDSPAN_INLINE_FUNCTION - static constexpr - index_type __static_extent() noexcept { - return __storage_t::template __get_static_n(); - } - -}; - -namespace detail { - -template > -struct __make_dextents; - -template -struct __make_dextents> { - using type = typename __make_dextents>::type; -}; - -template -struct __make_dextents> { - using type = ::std::experimental::extents; -}; - -} // end namespace detail - -template -using dextents = typename detail::__make_dextents::type; - -#if defined(_MDSPAN_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) -template -extents(IndexTypes...) - -> extents; -#endif - -namespace detail { - -template -struct __is_extents : ::std::false_type {}; - -template -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; - -} // end namespace detail -} // end namespace experimental -} // end namespace std -#endif From b83ac2fdb367ad1fea9f7b83989d863304800b64 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Wed, 1 Feb 2023 15:50:50 -0700 Subject: [PATCH 14/33] Renamed new extents file --- include/experimental/__p0009_bits/{extents2.hpp => extents.hpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename include/experimental/__p0009_bits/{extents2.hpp => extents.hpp} (100%) diff --git a/include/experimental/__p0009_bits/extents2.hpp b/include/experimental/__p0009_bits/extents.hpp similarity index 100% rename from include/experimental/__p0009_bits/extents2.hpp rename to include/experimental/__p0009_bits/extents.hpp From e550a7fc227dff2ce2e31ece17278b0471e91532 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Wed, 1 Feb 2023 15:52:24 -0700 Subject: [PATCH 15/33] Remove implementation detail files for old extents --- compilation_tests/ctest_standard_layout.cpp | 19 - .../ctest_trivially_copyable.cpp | 19 - .../__p0009_bits/layout_stride.hpp | 1 - .../__p0009_bits/maybe_static_value.hpp | 124 ---- .../standard_layout_static_array.hpp | 657 ------------------ .../__p0009_bits/static_array.hpp | 258 ------- include/experimental/mdspan | 1 - 7 files changed, 1079 deletions(-) delete mode 100644 include/experimental/__p0009_bits/maybe_static_value.hpp delete mode 100644 include/experimental/__p0009_bits/standard_layout_static_array.hpp delete mode 100644 include/experimental/__p0009_bits/static_array.hpp 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/include/experimental/__p0009_bits/layout_stride.hpp b/include/experimental/__p0009_bits/layout_stride.hpp index e15fed8b..e5a24d36 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" 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/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 From 02481f789ca1f07718e49f8247f637a700f8bb68 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Wed, 1 Feb 2023 15:59:11 -0700 Subject: [PATCH 16/33] Get rid of some old extents use code --- .../experimental/__p0009_bits/layout_left.hpp | 5 --- .../__p0009_bits/layout_right.hpp | 4 --- .../__p0009_bits/layout_stride.hpp | 36 ------------------- include/experimental/__p0009_bits/mdspan.hpp | 11 ------ 4 files changed, 56 deletions(-) diff --git a/include/experimental/__p0009_bits/layout_left.hpp b/include/experimental/__p0009_bits/layout_left.hpp index f11879b6..0bfa5680 100644 --- a/include/experimental/__p0009_bits/layout_left.hpp +++ b/include/experimental/__p0009_bits/layout_left.hpp @@ -47,13 +47,8 @@ class layout_left::mapping { _MDSPAN_HOST_DEVICE constexpr index_type __compute_offset( __rank_count, const I& i, Indices... idx) const { -#ifndef _MDSPAN_NEW_EXTENTS - return __compute_offset(__rank_count(), idx...) * - __extents.template __extent() + i; -#else return __compute_offset(__rank_count(), idx...) * __extents.extent(r) + i; -#endif } template diff --git a/include/experimental/__p0009_bits/layout_right.hpp b/include/experimental/__p0009_bits/layout_right.hpp index 1bb214d0..a3f3ab86 100644 --- a/include/experimental/__p0009_bits/layout_right.hpp +++ b/include/experimental/__p0009_bits/layout_right.hpp @@ -48,11 +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 { -#ifndef _MDSPAN_NEW_EXTENTS - return __compute_offset(offset * __extents.template __extent() + i,__rank_count(), idx...); -#else return __compute_offset(offset * __extents.extent(r) + i,__rank_count(), idx...); -#endif } template diff --git a/include/experimental/__p0009_bits/layout_stride.hpp b/include/experimental/__p0009_bits/layout_stride.hpp index e5a24d36..3da69507 100644 --- a/include/experimental/__p0009_bits/layout_stride.hpp +++ b/include/experimental/__p0009_bits/layout_stride.hpp @@ -188,15 +188,6 @@ struct layout_stride { } #endif -#ifndef _MDSPAN_NEW_EXTENTS - 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())...}; - } -#endif - template MDSPAN_INLINE_FUNCTION static constexpr size_t __return_zero() { return 0; } @@ -221,33 +212,6 @@ struct layout_stride { mapping(__base_t&& __b) : __base_t(::std::move(__b)) {} #endif - public: // but not really -#ifndef _MDSPAN_NEW_EXTENTS - 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 - ); - } -#endif - //---------------------------------------------------------------------------- - - public: //-------------------------------------------------------------------------------- diff --git a/include/experimental/__p0009_bits/mdspan.hpp b/include/experimental/__p0009_bits/mdspan.hpp index 822912d6..82408015 100644 --- a/include/experimental/__p0009_bits/mdspan.hpp +++ b/include/experimental/__p0009_bits/mdspan.hpp @@ -43,16 +43,6 @@ class mdspan template struct __deduction_workaround> { -#ifndef _MDSPAN_NEW_EXTENTS - 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)); - } - 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))); - } -#else MDSPAN_FORCE_INLINE_FUNCTION static constexpr size_t __size(mdspan const& __self) noexcept { return _MDSPAN_FOLD_TIMES_RIGHT((__self.__mapping_ref().extents().extent(Idxs)), /* * ... * */ size_t(1)); @@ -61,7 +51,6 @@ class mdspan bool __empty(mdspan const& __self) noexcept { return (__self.rank()>0) && _MDSPAN_FOLD_OR((__self.__mapping_ref().extents().extent(Idxs)==index_type(0))); } -#endif template MDSPAN_FORCE_INLINE_FUNCTION static constexpr ReferenceType __callop(mdspan const& __self, const array& indices) noexcept { From 69a9abb1fb47166856f5c7af5683684f96ec5c19 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Wed, 1 Feb 2023 15:59:29 -0700 Subject: [PATCH 17/33] Add missing copyright --- include/experimental/__p0009_bits/extents.hpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index 2118e9a4..fa0b233b 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -1,3 +1,19 @@ +//@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 "dynamic_extent.hpp" @@ -6,8 +22,6 @@ #endif #include "array" -#define _MDSPAN_NEW_EXTENTS - namespace std { namespace experimental { namespace detail { From ea1d9ca4ca17896cc36dd928e77ece31d2245756 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Fri, 3 Feb 2023 13:36:13 -0700 Subject: [PATCH 18/33] Update comments in extents implementation --- include/experimental/__p0009_bits/extents.hpp | 114 ++++++++++++------ 1 file changed, 76 insertions(+), 38 deletions(-) diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index fa0b233b..a5709e7d 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -27,7 +27,7 @@ namespace experimental { namespace detail { // Function used to check compatibility of extents in converting constructor -// can't be private member functions for some reason +// can't be private member functions for some reason. template static constexpr std::integral_constant __check_compatible_extents( std::integral_constant, @@ -49,7 +49,14 @@ __check_compatible_extents( return {}; } -// Implementation of Static Array, recursive implementation of get +// ------------------------------------------------------------------ +// ------------ 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 @@ -114,8 +121,15 @@ template struct static_array { constexpr static size_t size() { return sizeof...(Values); } }; -// index_sequence_scan takes indicies and provides get(r) and get() to get -// the sum of the first r-1 values + +// ------------------------------------------------------------------ +// ------------ index_sequence_scan --------------------------------- +// ------------------------------------------------------------------ + +// index_sequence_scan takes compile time values and provides get(r) +// and get() which return the sum of the first r-1 values. + +// Recursive implementation for get template struct index_sequence_scan_impl; template @@ -137,7 +151,7 @@ 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 + // evaluatable and also 0. MDSPAN_INLINE_FUNCTION constexpr static size_t get(size_t r) { return static_cast(R) > static_cast(r) ? FirstVal : 0; @@ -158,9 +172,15 @@ template <> struct index_sequence_scan_impl<0> { } }; -// Need this to have fully empty class maybe_static_array with all entries -// static Rather specialize this small helper class on size 0, then the whole -// thing +// ------------------------------------------------------------------ +// ------------ possibly_empty_array ------------------------------- +// ------------------------------------------------------------------ + +// 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 struct possibly_empty_array { T vals[N]; MDSPAN_INLINE_FUNCTION @@ -176,28 +196,48 @@ template struct possibly_empty_array { constexpr const T operator[](size_t) const { return T(); } }; -// maybe_static_array is an array which has a mix of static and dynamic values +// ------------------------------------------------------------------ +// ------------ 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 { 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; public: + // static mapping of indicies to the position in the dynamic values array using dyn_map_t = index_sequence_scan_impl<0, size_t(Values == dyn_tag)...>; + // two types for static and dynamic values using value_type = TDynamic; using static_value_type = TStatic; + // tag value indiciating dynamic value constexpr static static_value_type tag_value = dyn_tag; constexpr maybe_static_array() = default; - // constructors from dynamic_extentamic values only + // constructor for all static values + // TODO: add precondition check? + MDSPAN_TEMPLATE_REQUIRES(class... Vals, + /* requires */ ((m_size_dynamic == 0) && + (sizeof...(DynVals) > 0))) + MDSPAN_INLINE_FUNCTION + constexpr maybe_static_array(Vals...) : m_dyn_vals{} {} + + // constructors from dynamic values only MDSPAN_TEMPLATE_REQUIRES(class... DynVals, /* requires */ (sizeof...(DynVals) == m_size_dynamic && @@ -206,11 +246,6 @@ struct maybe_static_array { constexpr maybe_static_array(DynVals... vals) : m_dyn_vals{static_cast(vals)...} {} - MDSPAN_TEMPLATE_REQUIRES(class... DynVals, - /* requires */ ((m_size_dynamic == 0) && - (sizeof...(DynVals) > 0))) - MDSPAN_INLINE_FUNCTION - constexpr maybe_static_array(DynVals...) : m_dyn_vals{} {} MDSPAN_TEMPLATE_REQUIRES(class T, size_t N, /* requires */ (N == m_size_dynamic && N > 0)) @@ -223,7 +258,7 @@ struct maybe_static_array { 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 &) {} + constexpr maybe_static_array(const std::array &) : m_dyn_vals{} {} #ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES(class T, size_t N, @@ -249,6 +284,7 @@ struct maybe_static_array { if (static_val == dynamic_extent) { m_dyn_vals[dyn_map_t::get(r)] = values[r]; } +// Precondition check #ifdef _MDSPAN_DEBUG else { assert(values[r] == static_cast(static_val)); @@ -263,6 +299,7 @@ struct maybe_static_array { MDSPAN_INLINE_FUNCTION 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 @@ -271,6 +308,7 @@ struct maybe_static_array { if (static_val == dynamic_extent) { m_dyn_vals[dyn_map_t::get(r)] = static_cast(vals[r]); } +// Precondition check #ifdef _MDSPAN_DEBUG else { assert(static_cast(vals[r]) == @@ -325,27 +363,6 @@ struct maybe_static_array { constexpr static size_t size_dynamic() { return m_size_dynamic; } }; -#if 0 -template -struct maybe_static_array { - private: - using static_vals_t = static_array; - using dyn_map_t = index_sequence_scan_impl<0, size_t(Values==dyn_tag)...>; - constexpr static size_t m_size = sizeof...(Values); - constexpr static size_t m_size_dynamic = ((Values==dyn_tag) + ... + 0); - - - public: - - using value_type = TDynamic; - using static_value_type = TStatic; - constexpr static static_value_type tag_value = dyn_tag; - - constexpr static size_t size() { return 0; } - constexpr static size_t size_dynamic() { return 0; } -}; -#endif - } // namespace detail } // namespace experimental } // namespace std @@ -353,22 +370,33 @@ struct maybe_static_array { namespace std { namespace experimental { +// ------------------------------------------------------------------ +// ------------ extents --------------------------------------------- +// ------------------------------------------------------------------ + +// Class to describe the extents of a multi dimensional array. +// Used by mdspan, mdarray and layout mappings. +// See ISO C++ standard [mdspan.extents] + template class extents { public: - using rank_type = size_t; + // typedefs for integral types used using index_type = IndexType; using size_type = make_unsigned_t; + using rank_type = size_t; 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 constexpr static rank_type rank() { return m_rank; } MDSPAN_INLINE_FUNCTION @@ -381,9 +409,12 @@ template class extents { return vals_t::static_value(r); } + // [mdspan.extents.cons], constructors MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents() = default; + // Construction from just dynamic or all values. + // Precondition check is deferred to maybe_static_array constructor MDSPAN_TEMPLATE_REQUIRES( class... OtherIndexTypes, /* requires */ ( @@ -465,6 +496,8 @@ template class extents { } public: + + // Converting constructor from other extents specializations MDSPAN_TEMPLATE_REQUIRES( class OtherIndexType, size_t... OtherExtents, /* requires */ @@ -487,6 +520,7 @@ template class extents { std::integral_constant(), std::integral_constant(), other)) {} + // Comparison operator template MDSPAN_INLINE_FUNCTION friend constexpr bool operator==(const extents &lhs, @@ -507,6 +541,7 @@ template class extents { #endif }; +// Helper classes to implement dextents alias for extents namespace detail { template using dextents = typename detail::__make_dextents::type; +// Deduction guide for extents #if defined(_MDSPAN_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) template extents(IndexTypes...) @@ -541,6 +578,7 @@ extents(IndexTypes...) size_t((IndexTypes(), ::std::experimental::dynamic_extent))...>; #endif +// Helper type traits for identifying a class as extents. namespace detail { template struct __is_extents : ::std::false_type {}; From 176bc07e167638b9b5bb8cbb42d06b11a3f30a47 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Fri, 3 Feb 2023 14:28:14 -0700 Subject: [PATCH 19/33] Some code cleanup for extents based on code review --- include/experimental/__p0009_bits/extents.hpp | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index a5709e7d..8744d318 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -62,11 +62,11 @@ template struct static_array_impl; template struct static_array_impl { MDSPAN_INLINE_FUNCTION - constexpr static T value(size_t r) { + constexpr static T get(size_t r) { if (r == R) return FirstExt; else - return static_array_impl::value(r); + return static_array_impl::get(r); } template MDSPAN_INLINE_FUNCTION constexpr static T get() { #if MDSPAN_HAS_CXX_17 @@ -75,10 +75,7 @@ struct static_array_impl { else return static_array_impl::template get(); #else - if (r == R) - return FirstExt; - else - return static_array_impl::value(r); + get(r); #endif } }; @@ -87,7 +84,7 @@ struct static_array_impl { template struct static_array_impl { MDSPAN_INLINE_FUNCTION - constexpr static T value(int) { return FirstExt; } + constexpr static T get(int) { return FirstExt; } template MDSPAN_INLINE_FUNCTION constexpr static T get() { return FirstExt; } @@ -96,7 +93,7 @@ struct static_array_impl { // Don't start recursion if size 0 template struct static_array_impl<0, T> { MDSPAN_INLINE_FUNCTION - constexpr static T value(int) { return T(); } + constexpr static T get(int) { return T(); } template MDSPAN_INLINE_FUNCTION constexpr static T get() { return T(); } @@ -111,9 +108,9 @@ template struct static_array { using value_type = T; MDSPAN_INLINE_FUNCTION - constexpr T operator[](int r) const { return get(r); } + constexpr T operator[](int r) const { return impl_t::get(r); } MDSPAN_INLINE_FUNCTION - constexpr static T get(int r) { return impl_t::value(r); } + constexpr static T get(int r) { return impl_t::get(r); } template MDSPAN_INLINE_FUNCTION constexpr static T get() { return impl_t::template get(); } @@ -142,8 +139,15 @@ struct index_sequence_scan_impl { return 0; } template MDSPAN_INLINE_FUNCTION constexpr static size_t get() { - return r > R ? FirstVal + index_sequence_scan_impl::get(r) - : 0; +#if MDSPAN_HAS_CXX_17 + if constexpr (r > R) { + return FirstVal + index_sequence_scan_impl::get(r); + } else { + return 0; + } +#else + return get(r); +#endif } }; @@ -161,7 +165,15 @@ struct index_sequence_scan_impl { constexpr static size_t get(size_t r) { return R > r ? FirstVal : 0; } #endif template MDSPAN_INLINE_FUNCTION constexpr static size_t get() { - return R > r ? FirstVal : 0; +#if MDSPAN_HAS_CXX_17 + if constexpr (r > R) { + return FirstVal; + } else { + return 0; + } +#else + return get(r); +#endif } }; template <> struct index_sequence_scan_impl<0> { @@ -233,7 +245,7 @@ struct maybe_static_array { // TODO: add precondition check? MDSPAN_TEMPLATE_REQUIRES(class... Vals, /* requires */ ((m_size_dynamic == 0) && - (sizeof...(DynVals) > 0))) + (sizeof...(Vals) > 0))) MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(Vals...) : m_dyn_vals{} {} @@ -541,7 +553,7 @@ template class extents { #endif }; -// Helper classes to implement dextents alias for extents +// Recursive helper classes to implement dextents alias for extents namespace detail { template > : ::std::true_type {}; template -static constexpr bool __is_extents_v = __is_extents::value; +#if MDSPAN_HAS_CXX_17 +inline +#else +static +#endif +constexpr bool __is_extents_v = __is_extents::value; } // namespace detail } // namespace experimental From 0c6baecc04e6ef892128844441c9f06be6646da0 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Fri, 3 Feb 2023 15:43:34 -0700 Subject: [PATCH 20/33] Fix a test for explicit conversion construction of extents --- compilation_tests/ctest_extents_ctors.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/compilation_tests/ctest_extents_ctors.cpp b/compilation_tests/ctest_extents_ctors.cpp index cd05b1de..4f35fb3e 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, @@ -92,12 +93,18 @@ 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< - stdex::extents, - stdex::extents + stdex::extents, + stdex::extents >::value ); +#endif +#endif MDSPAN_STATIC_TEST( From 99ed11bbfc395cb1f826ab121284f687ac13d654 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Fri, 3 Feb 2023 16:24:02 -0700 Subject: [PATCH 21/33] Fix some small deviations from standard for new extents Also tests for those. Co-authored-by: Damien L-G --- compilation_tests/ctest_extents_ctors.cpp | 86 +++++++++++++++++-- include/experimental/__p0009_bits/extents.hpp | 32 +++---- 2 files changed, 98 insertions(+), 20 deletions(-) diff --git a/compilation_tests/ctest_extents_ctors.cpp b/compilation_tests/ctest_extents_ctors.cpp index 4f35fb3e..390f6500 100644 --- a/compilation_tests/ctest_extents_ctors.cpp +++ b/compilation_tests/ctest_extents_ctors.cpp @@ -57,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 ); @@ -78,6 +79,7 @@ MDSPAN_STATIC_TEST( >::value ); +// conversion construction from extents MDSPAN_STATIC_TEST( std::is_constructible< stdex::extents, @@ -93,6 +95,13 @@ 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. @@ -109,25 +118,72 @@ MDSPAN_STATIC_TEST( 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, @@ -143,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, @@ -150,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/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index 8744d318..4a3821b6 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -410,20 +410,20 @@ template class extents { public: // [mdspan.extents.obs], observers of multidimensional index space MDSPAN_INLINE_FUNCTION - constexpr static rank_type rank() { return m_rank; } + constexpr static rank_type rank() noexcept { return m_rank; } MDSPAN_INLINE_FUNCTION - constexpr static rank_type rank_dynamic() { return m_rank_dynamic; } + constexpr static rank_type rank_dynamic() noexcept { return m_rank_dynamic; } MDSPAN_INLINE_FUNCTION - constexpr index_type extent(rank_type r) const { return m_vals.value(r); } + 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) { + constexpr static size_t static_extent(rank_type r) noexcept { return vals_t::static_value(r); } // [mdspan.extents.cons], constructors MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr extents() = default; + constexpr extents() noexcept = default; // Construction from just dynamic or all values. // Precondition check is deferred to maybe_static_array constructor @@ -437,19 +437,20 @@ template class extents { (sizeof...(OtherIndexTypes) == m_rank || sizeof...(OtherIndexTypes) == m_rank_dynamic))) MDSPAN_INLINE_FUNCTION - constexpr extents(OtherIndexTypes... dynvals) + constexpr explicit extents(OtherIndexTypes... dynvals) noexcept : m_vals(static_cast(dynvals)...) {} MDSPAN_TEMPLATE_REQUIRES( class OtherIndexType, size_t N, /* requires */ ( - // _MDSPAN_TRAIT(is_convertible, OtherIndexType, index_type) && - // _MDSPAN_TRAIT(is_nothrow_constructible, index_type, - // OtherIndexType) && + _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 - constexpr extents(const array &exts) + MDSPAN_CONDITIONAL_EXPLICIT(N != m_rank_dynamic) + constexpr extents(const array &exts) noexcept : m_vals(std::move(exts)) {} #ifdef __cpp_lib_span @@ -460,7 +461,8 @@ template class extents { _MDSPAN_TRAIT(is_nothrow_constructible, index_type, OtherIndexType) && (N == m_rank || N == m_rank_dynamic))) MDSPAN_INLINE_FUNCTION - constexpr extents(const span &exts) + MDSPAN_CONDITIONAL_EXPLICIT(N != m_rank_dynamic) + constexpr extents(const span &exts) noexcept : m_vals(std::move(exts)) {} #endif @@ -476,7 +478,7 @@ template class extents { vals_t __construct_vals_from_extents(std::integral_constant, std::integral_constant, const OtherExtents &exts, - DynamicValues... dynamic_values) { + DynamicValues... dynamic_values) noexcept { return __construct_vals_from_extents( std::integral_constant(), std::integral_constant(), exts, dynamic_values..., @@ -490,7 +492,7 @@ template class extents { vals_t __construct_vals_from_extents(std::integral_constant, std::integral_constant, const OtherExtents &exts, - DynamicValues... dynamic_values) { + DynamicValues... dynamic_values) noexcept { return __construct_vals_from_extents( std::integral_constant(), std::integral_constant(), exts, dynamic_values...); @@ -503,7 +505,7 @@ template class extents { vals_t __construct_vals_from_extents(std::integral_constant, std::integral_constant, const OtherExtents &, - DynamicValues... dynamic_values) { + DynamicValues... dynamic_values) noexcept { return vals_t{static_cast(dynamic_values)...}; } @@ -527,7 +529,7 @@ template class extents { ...) || (std::numeric_limits::max() < std::numeric_limits::max())) - constexpr extents(const extents &other) + constexpr extents(const extents &other) noexcept : m_vals(__construct_vals_from_extents( std::integral_constant(), std::integral_constant(), other)) {} From d036d5f31f7ce0cfd76084d6e968613fce6f8200 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Thu, 9 Feb 2023 12:35:53 -0700 Subject: [PATCH 22/33] Apply suggestions from code review Co-authored-by: Mark Hoemmen --- include/experimental/__p0009_bits/extents.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index 4a3821b6..16321df0 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -18,9 +18,9 @@ #include "dynamic_extent.hpp" #ifdef __cpp_lib_span -#include "span" +#include #endif -#include "array" +#include namespace std { namespace experimental { @@ -84,7 +84,7 @@ struct static_array_impl { template struct static_array_impl { MDSPAN_INLINE_FUNCTION - constexpr static T get(int) { return FirstExt; } + constexpr static T get(size_t) { return FirstExt; } template MDSPAN_INLINE_FUNCTION constexpr static T get() { return FirstExt; } @@ -93,7 +93,7 @@ struct static_array_impl { // Don't start recursion if size 0 template struct static_array_impl<0, T> { MDSPAN_INLINE_FUNCTION - constexpr static T get(int) { return T(); } + constexpr static T get(size_t) { return T(); } template MDSPAN_INLINE_FUNCTION constexpr static T get() { return T(); } @@ -230,13 +230,13 @@ struct maybe_static_array { m_dyn_vals; public: - // static mapping of indicies to the position in the dynamic values array + // static mapping of indices to the position in the dynamic values array using dyn_map_t = index_sequence_scan_impl<0, size_t(Values == dyn_tag)...>; // two types for static and dynamic values using value_type = TDynamic; using static_value_type = TStatic; - // tag value indiciating dynamic value + // tag value indicating dynamic value constexpr static static_value_type tag_value = dyn_tag; constexpr maybe_static_array() = default; From 49e116273b29ca39fba1ed73ff4f3a273d61d777 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Wed, 15 Mar 2023 13:27:49 -0600 Subject: [PATCH 23/33] Fix MSVC 14 issue Co-Authored-By: Wesley Maxey <71408887+wmaxey@users.noreply.github.com> --- include/experimental/__p0009_bits/extents.hpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index 16321df0..401fa18f 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -36,12 +36,17 @@ static constexpr std::integral_constant __check_compatible_extents( return {}; } +// This helper prevents ICE's on MSVC. +template +struct __compare_extent_compatible : std::integral_constant +{}; + template static constexpr std::integral_constant< - bool, _MDSPAN_FOLD_AND((Extents == dynamic_extent || - OtherExtents == dynamic_extent || - Extents == OtherExtents) /* && ... */ - )> + bool, _MDSPAN_FOLD_AND(__compare_extent_compatible::value)> __check_compatible_extents( std::integral_constant, std::integer_sequence, From cd39b4c94599e5d616ffc0a7b92c1de86156867f Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Thu, 16 Mar 2023 15:32:12 -0600 Subject: [PATCH 24/33] Add static assertion to check saneness of types in maybe_static_array --- include/experimental/__p0009_bits/extents.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index 401fa18f..677fc8f2 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -223,6 +223,10 @@ template struct possibly_empty_array { // 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; From 002f2ad59d5f9c5f7175b8b45a8cf4c6b0940f6a Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Thu, 16 Mar 2023 16:05:53 -0600 Subject: [PATCH 25/33] Fix use of int and don't compile benchmarks in C++23 mode --- CMakeLists.txt | 4 ++-- include/experimental/__p0009_bits/extents.hpp | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e75f3c7b..7dbf8dfe 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/20 or newer.") endif() endif() diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index 677fc8f2..0c88958d 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -113,9 +113,9 @@ template struct static_array { using value_type = T; MDSPAN_INLINE_FUNCTION - constexpr T operator[](int r) const { return impl_t::get(r); } + constexpr T operator[](size_t r) const { return impl_t::get(r); } MDSPAN_INLINE_FUNCTION - constexpr static T get(int r) { return impl_t::get(r); } + constexpr static T get(size_t r) { return impl_t::get(r); } template MDSPAN_INLINE_FUNCTION constexpr static T get() { return impl_t::template get(); } @@ -366,16 +366,17 @@ struct maybe_static_array { // access functions MDSPAN_INLINE_FUNCTION - constexpr static TStatic static_value(int r) { return static_vals_t::get(r); } + constexpr static TStatic static_value(size_t r) { return static_vals_t::get(r); } MDSPAN_INLINE_FUNCTION - constexpr TDynamic value(int r) const { + constexpr TDynamic value(size_t r) const { TStatic static_val = static_vals_t::get(r); return static_val == dynamic_extent ? m_dyn_vals[dyn_map_t::get(r)] : static_cast(static_val); } MDSPAN_INLINE_FUNCTION - constexpr TDynamic operator[](int r) const { return value(r); } + constexpr TDynamic operator[](size_t r) const { return value(r); } + // observers MDSPAN_INLINE_FUNCTION From 2a782c281feebe8c8e8a93e2fb99f93674e29695 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Mon, 3 Apr 2023 17:40:47 -0600 Subject: [PATCH 26/33] Apply suggestions from code review Co-authored-by: Mark Hoemmen Co-authored-by: Nicolas Morales --- CMakeLists.txt | 2 +- include/experimental/__p0009_bits/extents.hpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7dbf8dfe..2bd8d6c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,7 +197,7 @@ if(MDSPAN_ENABLE_BENCHMARKS) 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 or C++23 mode. Turn MDSPAN_ENABLE_BENCHMARKS OFF or use C++17/20 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/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index 0c88958d..d1043ccd 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -240,7 +240,7 @@ struct maybe_static_array { public: // static mapping of indices to the position in the dynamic values array - using dyn_map_t = index_sequence_scan_impl<0, size_t(Values == dyn_tag)...>; + using dyn_map_t = index_sequence_scan_impl<0, static_cast(Values == dyn_tag)...>; // two types for static and dynamic values using value_type = TDynamic; @@ -302,7 +302,7 @@ struct maybe_static_array { 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 == dynamic_extent) { + if (static_val == dyn_tag) { m_dyn_vals[dyn_map_t::get(r)] = values[r]; } // Precondition check @@ -326,7 +326,7 @@ struct maybe_static_array { #endif for (size_t r = 0; r < m_size; r++) { TStatic static_val = static_vals_t::get(r); - if (static_val == dynamic_extent) { + if (static_val == dyn_tag) { m_dyn_vals[dyn_map_t::get(r)] = static_cast(vals[r]); } // Precondition check @@ -351,7 +351,7 @@ struct maybe_static_array { #endif for (size_t r = 0; r < m_size; r++) { TStatic static_val = static_vals_t::get(r); - if (static_val == dynamic_extent) { + if (static_val == dyn_tag) { m_dyn_vals[dyn_map_t::get(r)] = static_cast(vals[r]); } #ifdef _MDSPAN_DEBUG @@ -371,7 +371,7 @@ struct maybe_static_array { MDSPAN_INLINE_FUNCTION constexpr TDynamic value(size_t r) const { TStatic static_val = static_vals_t::get(r); - return static_val == dynamic_extent ? m_dyn_vals[dyn_map_t::get(r)] + return static_val == dyn_tag ? m_dyn_vals[dyn_map_t::get(r)] : static_cast(static_val); } MDSPAN_INLINE_FUNCTION From 588a50ac1b81a73bef11f17813d417783ff99690 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Mon, 3 Apr 2023 17:45:52 -0600 Subject: [PATCH 27/33] Make maybe-static-array dyn_map_t private --- include/experimental/__p0009_bits/extents.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index d1043ccd..1705e1af 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -238,9 +238,9 @@ struct maybe_static_array { _MDSPAN_NO_UNIQUE_ADDRESS possibly_empty_array m_dyn_vals; -public: // 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; From b568d51523430cd4597de064c9874c8239a557a1 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Mon, 3 Apr 2023 17:59:01 -0600 Subject: [PATCH 28/33] Make static_array inherit from its impl type, and check extents mandate --- include/experimental/__p0009_bits/extents.hpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index 1705e1af..d4acc98a 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -105,20 +105,12 @@ template struct static_array_impl<0, T> { }; // Static array, provides get(), get(r) and operator[r] -template struct static_array { -private: - using impl_t = static_array_impl<0, T, Values...>; +template struct static_array: + public static_array_impl<0, T, Values...> { public: using value_type = T; - MDSPAN_INLINE_FUNCTION - constexpr T operator[](size_t r) const { return impl_t::get(r); } - MDSPAN_INLINE_FUNCTION - constexpr static T get(size_t r) { return impl_t::get(r); } - template MDSPAN_INLINE_FUNCTION constexpr static T get() { - return impl_t::template get(); - } MDSPAN_INLINE_FUNCTION constexpr static size_t size() { return sizeof...(Values); } }; @@ -407,6 +399,8 @@ template class extents { 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 = From d9f471573fbffc67b23e92523c584f1f666942ae Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Mon, 3 Apr 2023 18:03:22 -0600 Subject: [PATCH 29/33] Remove some leftover newextents/oldextents stuff --- include/experimental/__p0009_bits/layout_stride.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/experimental/__p0009_bits/layout_stride.hpp b/include/experimental/__p0009_bits/layout_stride.hpp index 3da69507..cac4f900 100644 --- a/include/experimental/__p0009_bits/layout_stride.hpp +++ b/include/experimental/__p0009_bits/layout_stride.hpp @@ -239,11 +239,7 @@ struct layout_stride { #else : __base_t(__base_t{__member_pair_t( #endif -#ifndef _MDSPAN_NEW_EXTENT2S e, __strides_storage_t(__impl::fill_strides(s)) -#else - e, __strides_storage_t(s) -#endif #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) } #else From 952be00273e1e0a6b85a03a8331ce3998551f210 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Tue, 4 Apr 2023 09:07:17 -0600 Subject: [PATCH 30/33] Fix two build issues on NVHPC --- include/experimental/__p0009_bits/extents.hpp | 2 ++ include/experimental/__p0009_bits/mdspan.hpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index d4acc98a..81b8dc78 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -22,6 +22,8 @@ #endif #include +#include + namespace std { namespace experimental { namespace detail { diff --git a/include/experimental/__p0009_bits/mdspan.hpp b/include/experimental/__p0009_bits/mdspan.hpp index 82408015..c81a8836 100644 --- a/include/experimental/__p0009_bits/mdspan.hpp +++ b/include/experimental/__p0009_bits/mdspan.hpp @@ -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) From e78a29c88f25414b1dea05cbd38a9586ea2bcce1 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Tue, 4 Apr 2023 09:14:13 -0600 Subject: [PATCH 31/33] Remove unused function in the scan --- include/experimental/__p0009_bits/extents.hpp | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index 81b8dc78..8cc99390 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -137,17 +137,6 @@ struct index_sequence_scan_impl { else return 0; } - template MDSPAN_INLINE_FUNCTION constexpr static size_t get() { -#if MDSPAN_HAS_CXX_17 - if constexpr (r > R) { - return FirstVal + index_sequence_scan_impl::get(r); - } else { - return 0; - } -#else - return get(r); -#endif - } }; template @@ -163,24 +152,10 @@ struct index_sequence_scan_impl { MDSPAN_INLINE_FUNCTION constexpr static size_t get(size_t r) { return R > r ? FirstVal : 0; } #endif - template MDSPAN_INLINE_FUNCTION constexpr static size_t get() { -#if MDSPAN_HAS_CXX_17 - if constexpr (r > R) { - return FirstVal; - } else { - return 0; - } -#else - return get(r); -#endif - } }; template <> struct index_sequence_scan_impl<0> { MDSPAN_INLINE_FUNCTION constexpr static size_t get(size_t) { return 0; } - template MDSPAN_INLINE_FUNCTION constexpr static size_t get() { - return 0; - } }; // ------------------------------------------------------------------ From c93cd34cade1c3a45ab1d46f83e2697da7268bf0 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Tue, 4 Apr 2023 10:38:36 -0600 Subject: [PATCH 32/33] Fix build of examples with bracket operator --- examples/dot_product/dot_product.cpp | 8 ++++++++ examples/tiled_layout/simple_tiled_layout.cpp | 10 ++++++++++ 2 files changed, 18 insertions(+) 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; + } } From 2d8f8efd33872b52c34fca1abd446ba68a68de7f Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Tue, 4 Apr 2023 11:21:34 -0600 Subject: [PATCH 33/33] Apply suggestions from code review Co-authored-by: Mark Hoemmen --- include/experimental/__p0009_bits/extents.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/experimental/__p0009_bits/extents.hpp b/include/experimental/__p0009_bits/extents.hpp index 8cc99390..2295d81f 100644 --- a/include/experimental/__p0009_bits/extents.hpp +++ b/include/experimental/__p0009_bits/extents.hpp @@ -22,14 +22,14 @@ #endif #include -#include +#include namespace std { namespace experimental { namespace detail { // Function used to check compatibility of extents in converting constructor -// can't be private member functions for some reason. +// can't be a private member function for some reason. template static constexpr std::integral_constant __check_compatible_extents( std::integral_constant,