19 #include "extents.hpp" 20 #include "trait_backports.hpp" 21 #include "compressed_pair.hpp" 23 #if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) 24 # include "no_unique_address.hpp" 33 #if defined(_MDSPAN_USE_CONCEPTS) && MDSPAN_HAS_CXX_20 38 namespace experimental {
41 template<
class Extents>
45 template<
class Extents>
50 template<
class Layout,
class Mapping>
51 constexpr
bool __is_mapping_of =
52 is_same<typename Layout::template mapping<typename Mapping::extents_type>, Mapping>
::value;
54 #if defined(_MDSPAN_USE_CONCEPTS) && MDSPAN_HAS_CXX_20 56 concept __layout_mapping_alike = requires {
58 { M::is_always_strided() } -> same_as<bool>;
59 { M::is_always_exhaustive() } -> same_as<bool>;
60 { M::is_always_unique() } -> same_as<bool>;
69 template <
class Extents>
71 #if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS)
73 detail::__compressed_pair<
75 std::array<typename Extents::index_type, Extents::rank()>
81 using extents_type = Extents;
82 using index_type =
typename extents_type::index_type;
83 using size_type =
typename extents_type::size_type;
84 using rank_type =
typename extents_type::rank_type;
88 static_assert(detail::__is_extents_v<Extents>,
"std::experimental::layout_stride::mapping must be instantiated with a specialization of std::experimental::extents.");
95 using __strides_storage_t = array<index_type, extents_type::rank()>;
98 #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) 104 MDSPAN_FORCE_INLINE_FUNCTION constexpr __strides_storage_t
const&
105 __strides_storage()
const noexcept {
106 #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) 107 return __members.__second();
109 return this->__base_t::__ref().__second();
112 MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 __strides_storage_t&
113 __strides_storage() noexcept {
114 #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) 115 return __members.__second();
117 return this->__base_t::__ref().__second();
121 template<
class SizeType, ::std::size_t ... Ep, ::std::size_t ... Idx>
124 return _MDSPAN_FOLD_TIMES_RIGHT( static_cast<index_type>(
extents().extent(Idx)), 1 );
136 struct __deduction_workaround;
138 template <
size_t... Idxs>
139 struct __deduction_workaround<index_sequence<Idxs...>>
141 template <
class OtherExtents>
142 MDSPAN_INLINE_FUNCTION
144 return _MDSPAN_FOLD_AND((
self.stride(Idxs) == other.stride(Idxs)) )
145 && _MDSPAN_FOLD_AND((
self.
extents().extent(Idxs) == other.extents().extent(Idxs)) );
147 template <
class OtherExtents>
148 MDSPAN_INLINE_FUNCTION
150 return _MDSPAN_FOLD_OR((
self.stride(Idxs) != other.stride(Idxs)) )
151 || _MDSPAN_FOLD_OR((
self.
extents().extent(Idxs) != other.extents().extent(Idxs)) );
154 template <
class... Integral>
155 MDSPAN_FORCE_INLINE_FUNCTION
156 static constexpr
size_t _call_op_impl(
mapping const&
self, Integral... idxs) noexcept {
157 return _MDSPAN_FOLD_PLUS_RIGHT((idxs *
self.stride(Idxs)), 0);
160 MDSPAN_INLINE_FUNCTION
161 static constexpr
size_t _req_span_size_impl(
mapping const&
self) noexcept {
163 return __impl::_call_op_impl(
self, (
self.
extents().
template __extent<Idxs>() - 1)...) + 1;
166 template<
class OtherMapping>
167 MDSPAN_INLINE_FUNCTION
168 static constexpr
const __strides_storage_t fill_strides(
const OtherMapping& map) {
169 return __strides_storage_t{
static_cast<index_type
>(map.stride(Idxs))...};
172 MDSPAN_INLINE_FUNCTION
173 static constexpr
const __strides_storage_t& fill_strides(
const __strides_storage_t& s) {
177 template<
class IntegralType>
178 MDSPAN_INLINE_FUNCTION
179 static constexpr
const __strides_storage_t fill_strides(
const array<IntegralType,extents_type::rank()>& s) {
180 return __strides_storage_t{
static_cast<index_type
>(s[Idxs])...};
183 #ifdef __cpp_lib_span 184 template<
class IntegralType>
185 MDSPAN_INLINE_FUNCTION
186 static constexpr
const __strides_storage_t fill_strides(
const span<IntegralType,extents_type::rank()>& s) {
187 return __strides_storage_t{
static_cast<index_type
>(s[Idxs])...};
192 MDSPAN_INLINE_FUNCTION
193 static constexpr
size_t __return_zero() {
return 0; }
195 template<
class Mapping>
196 MDSPAN_INLINE_FUNCTION
197 static constexpr
typename Mapping::index_type
198 __OFFSET(
const Mapping& m) {
return m(__return_zero<Idxs>()...); }
202 using __impl = __deduction_workaround<make_index_sequence<Extents::rank()>>;
207 #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) 208 MDSPAN_INLINE_FUNCTION constexpr
explicit 211 MDSPAN_INLINE_FUNCTION constexpr
explicit 219 MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() noexcept =
default;
220 MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping(mapping
const&) noexcept =
default;
222 MDSPAN_TEMPLATE_REQUIRES(
227 _MDSPAN_TRAIT(is_convertible,
const remove_const_t<IntegralTypes>&,
typename Extents::index_type) &&
228 _MDSPAN_TRAIT(is_nothrow_constructible,
typename Extents::index_type,
const remove_const_t<IntegralTypes>&)
231 MDSPAN_INLINE_FUNCTION
234 extents_type
const& e,
235 array<IntegralTypes, extents_type::rank()>
const& s
237 #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) 242 e, __strides_storage_t(__impl::fill_strides(s))
243 #
if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS)
259 #ifdef __cpp_lib_span 260 MDSPAN_TEMPLATE_REQUIRES(
265 _MDSPAN_TRAIT(is_convertible,
const remove_const_t<IntegralTypes>&,
typename Extents::index_type) &&
266 _MDSPAN_TRAIT(is_nothrow_constructible,
typename Extents::index_type,
const remove_const_t<IntegralTypes>&)
269 MDSPAN_INLINE_FUNCTION
272 extents_type
const& e,
273 span<IntegralTypes, extents_type::rank()>
const& s
275 #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) 280 e, __strides_storage_t(__impl::fill_strides(s))
281 #
if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS)
296 #endif // __cpp_lib_span 298 #if !(defined(_MDSPAN_USE_CONCEPTS) && MDSPAN_HAS_CXX_20) 299 MDSPAN_TEMPLATE_REQUIRES(
300 class StridedLayoutMapping,
302 _MDSPAN_TRAIT(is_constructible, extents_type,
typename StridedLayoutMapping::extents_type) &&
303 detail::__is_mapping_of<typename StridedLayoutMapping::layout_type, StridedLayoutMapping> &&
304 StridedLayoutMapping::is_always_unique() &&
305 StridedLayoutMapping::is_always_strided()
309 template<
class Str
idedLayoutMapping>
311 detail::__layout_mapping_alike<StridedLayoutMapping> &&
312 _MDSPAN_TRAIT(is_constructible, extents_type,
typename StridedLayoutMapping::extents_type) &&
313 StridedLayoutMapping::is_always_unique() &&
314 StridedLayoutMapping::is_always_strided()
317 MDSPAN_CONDITIONAL_EXPLICIT(
319 (detail::__is_mapping_of<layout_left, StridedLayoutMapping> ||
320 detail::__is_mapping_of<layout_right, StridedLayoutMapping> ||
321 detail::__is_mapping_of<layout_stride, StridedLayoutMapping>)
323 MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14
324 mapping(StridedLayoutMapping
const& other) noexcept
325 #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) 330 other.extents(), __strides_storage_t(__impl::fill_strides(other))
331 #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) 347 MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED
348 mapping& operator=(mapping
const&) noexcept =
default;
350 MDSPAN_INLINE_FUNCTION constexpr
const extents_type&
extents()
const noexcept {
351 #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) 352 return __members.__first();
354 return this->__base_t::__ref().__first();
358 MDSPAN_INLINE_FUNCTION
359 constexpr array< index_type, extents_type::rank() > strides()
const noexcept {
360 return __strides_storage();
363 MDSPAN_INLINE_FUNCTION
364 constexpr index_type required_span_size()
const noexcept {
365 index_type span_size = 1;
366 for(
unsigned r = 0; r < extents_type::rank(); r++) {
368 if(
extents().extent(r)==0)
return 0;
369 span_size += (
static_cast<index_type
>(
extents().extent(r) - 1 ) * __strides_storage()[r]);
375 MDSPAN_TEMPLATE_REQUIRES(
378 sizeof...(Indices) == Extents::rank() &&
379 _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_convertible, Indices, index_type) ) &&
380 _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_nothrow_constructible, index_type, Indices) )
383 MDSPAN_FORCE_INLINE_FUNCTION
384 constexpr index_type operator()(Indices... idxs)
const noexcept {
385 return static_cast<index_type
>(__impl::_call_op_impl(*
this, static_cast<index_type>(idxs)...));
388 MDSPAN_INLINE_FUNCTION
static constexpr
bool is_always_unique() noexcept {
return true; }
389 MDSPAN_INLINE_FUNCTION
static constexpr
bool is_always_exhaustive() noexcept {
392 MDSPAN_INLINE_FUNCTION
static constexpr
bool is_always_strided() noexcept {
return true; }
394 MDSPAN_INLINE_FUNCTION
static constexpr
bool is_unique() noexcept {
return true; }
395 MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14
bool is_exhaustive()
const noexcept {
396 return required_span_size() == __get_size(
extents(), make_index_sequence<extents_type::rank()>());
398 MDSPAN_INLINE_FUNCTION
static constexpr
bool is_strided() noexcept {
return true; }
401 MDSPAN_INLINE_FUNCTION
402 constexpr index_type stride(rank_type r)
const noexcept
403 #if MDSPAN_HAS_CXX_20 404 requires ( Extents::rank() > 0 )
407 return __strides_storage()[r];
410 #if !(defined(_MDSPAN_USE_CONCEPTS) && MDSPAN_HAS_CXX_20) 411 MDSPAN_TEMPLATE_REQUIRES(
412 class StridedLayoutMapping,
414 detail::__is_mapping_of<typename StridedLayoutMapping::layout_type, StridedLayoutMapping> &&
415 (extents_type::rank() == StridedLayoutMapping::extents_type::rank()) &&
416 StridedLayoutMapping::is_always_strided()
420 template<
class Str
idedLayoutMapping>
422 detail::__layout_mapping_alike<StridedLayoutMapping> &&
423 (extents_type::rank() == StridedLayoutMapping::extents_type::rank()) &&
424 StridedLayoutMapping::is_always_strided()
427 MDSPAN_INLINE_FUNCTION
428 friend constexpr
bool operator==(
const mapping& x,
const StridedLayoutMapping& y) noexcept {
429 bool strides_match =
true;
430 for(rank_type r = 0; r < extents_type::rank(); r++)
431 strides_match = strides_match && (x.stride(r) == y.stride(r));
432 return (x.extents() == y.extents()) &&
433 (__impl::__OFFSET(y)==
static_cast<typename StridedLayoutMapping::index_type
>(0)) &&
438 MDSPAN_TEMPLATE_REQUIRES(
441 (extents_type::rank() == OtherExtents::rank())
444 MDSPAN_INLINE_FUNCTION
446 return __impl::_eq_impl(lhs, rhs);
449 #if !MDSPAN_HAS_CXX_20 450 MDSPAN_TEMPLATE_REQUIRES(
451 class StridedLayoutMapping,
453 detail::__is_mapping_of<typename StridedLayoutMapping::layout_type, StridedLayoutMapping> &&
454 (extents_type::rank() == StridedLayoutMapping::extents_type::rank()) &&
455 StridedLayoutMapping::is_always_strided()
458 MDSPAN_INLINE_FUNCTION
459 friend constexpr
bool operator!=(
const mapping& x,
const StridedLayoutMapping& y) noexcept {
463 MDSPAN_TEMPLATE_REQUIRES(
466 (extents_type::rank() == OtherExtents::rank())
469 MDSPAN_INLINE_FUNCTION
471 return __impl::_not_eq_impl(lhs, rhs);
Definition: layout_stride.hpp:44
Definition: compressed_pair.hpp:31
Definition: layout_right.hpp:29
Definition: layout_stride.hpp:70
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
Definition: no_unique_address.hpp:28
Definition: layout_stride.hpp:40
Definition: layout_stride.hpp:68
Definition: trait_backports.hpp:64
Definition: layout_left.hpp:28
Definition: extents.hpp:372