codekingpro/portable-devtools
114k
1/*2//@HEADER3// ************************************************************************4//5// Kokkos v. 2.06// Copyright (2019) Sandia Corporation7//8// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,9// the U.S. Government retains certain rights in this software.10//11// Redistribution and use in source and binary forms, with or without12// modification, are permitted provided that the following conditions are13// met:14//15// 1. Redistributions of source code must retain the above copyright16// notice, this list of conditions and the following disclaimer.17//18// 2. Redistributions in binary form must reproduce the above copyright19// notice, this list of conditions and the following disclaimer in the20// documentation and/or other materials provided with the distribution.21//22// 3. Neither the name of the Corporation nor the names of the23// contributors may be used to endorse or promote products derived from24// this software without specific prior written permission.25//26// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY27// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE28// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR29// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE30// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,31// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,32// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR33// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING35// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS36// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.37//38// Questions? Contact Christian R. Trott (crtrott@sandia.gov)39//40// ************************************************************************41//@HEADER42*/43 44#ifndef _LIBCUDACXX___MDSPAN_LAYOUT_STRIDE_HPP45#define _LIBCUDACXX___MDSPAN_LAYOUT_STRIDE_HPP46 47#ifndef __cuda_std__48#include <__config>49#endif // __cuda_std__50 51#include "../__mdspan/compressed_pair.h"52#include "../__mdspan/extents.h"53#include "../__mdspan/macros.h"54#ifdef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS55#include "../__mdspan/no_unique_address.h"56#endif57#include "../__mdspan/static_array.h"58#include "../__type_traits/is_same.h"59#include "../__type_traits/is_constructible.h"60#include "../__type_traits/is_convertible.h"61#include "../__type_traits/is_nothrow_constructible.h"62#include "../__type_traits/remove_const.h"63#include "../__utility/integer_sequence.h"64#include "../__utility/move.h"65#include "../algorithm"66#include "../array"67#if __MDSPAN_USE_CONCEPTS && __MDSPAN_HAS_CXX_2068#include "../concepts"69#endif70#include "../numeric"71#include "../span"72 73#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)74# pragma GCC system_header75#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)76# pragma clang system_header77#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)78# pragma system_header79#endif // no system header80 81_LIBCUDACXX_BEGIN_NAMESPACE_STD82 83#if _LIBCUDACXX_STD_VER > 1184 85struct layout_left {86 template<class _Extents>87 class mapping;88};89struct layout_right {90 template<class _Extents>91 class mapping;92};93 94namespace __detail {95 template<class _Layout, class _Mapping>96 constexpr bool __is_mapping_of =97 _CUDA_VSTD::is_same<typename _Layout::template mapping<typename _Mapping::extents_type>, _Mapping>::value;98 99#if __MDSPAN_USE_CONCEPTS && __MDSPAN_HAS_CXX_20100 template<class _Mp>101 concept __layout_mapping_alike = requires {102 requires __is_extents<typename _Mp::extents_type>::value;103 { _Mp::is_always_strided() } -> same_as<bool>;104 { _Mp::is_always_exhaustive() } -> same_as<bool>;105 { _Mp::is_always_unique() } -> same_as<bool>;106 bool_constant<_Mp::is_always_strided()>::value;107 bool_constant<_Mp::is_always_exhaustive()>::value;108 bool_constant<_Mp::is_always_unique()>::value;109 };110#endif111} // namespace __detail112 113struct layout_stride {114 template <class _Extents>115 class mapping116#ifdef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS117 : private __detail::__no_unique_address_emulation<118 __detail::__compressed_pair<119 _Extents,120 _CUDA_VSTD::array<typename _Extents::index_type, _Extents::rank()>121 >122 >123#endif124 {125 public:126 using extents_type = _Extents;127 using index_type = typename extents_type::index_type;128 using size_type = typename extents_type::size_type;129 using rank_type = typename extents_type::rank_type;130 using layout_type = layout_stride;131 132 // This could be a `requires`, but I think it's better and clearer as a `static_assert`.133 static_assert(__detail::__is_extents_v<_Extents>, "layout_stride::mapping must be instantiated with a specialization of _CUDA_VSTD::extents.");134 135 136 private:137 138 //----------------------------------------------------------------------------139 140 using __strides_storage_t = _CUDA_VSTD::array<index_type, extents_type::rank()>;//_CUDA_VSTD::dextents<index_type, extents_type::rank()>;141 using __member_pair_t = __detail::__compressed_pair<extents_type, __strides_storage_t>;142 143#ifndef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS144 _LIBCUDACXX_NO_UNIQUE_ADDRESS __member_pair_t __members;145#else146 using __base_t = __detail::__no_unique_address_emulation<__member_pair_t>;147#endif148 149 __MDSPAN_FORCE_INLINE_FUNCTION constexpr __strides_storage_t const&150 __strides_storage() const noexcept {151#ifndef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS152 return __members.__second();153#else154 return this->__base_t::__ref().__second();155#endif156 }157 __MDSPAN_FORCE_INLINE_FUNCTION constexpr __strides_storage_t&158 __strides_storage() noexcept {159#ifndef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS160 return __members.__second();161#else162 return this->__base_t::__ref().__second();163#endif164 }165 166 template<class _SizeType, size_t ... _Ep, size_t ... _Idx>167 _LIBCUDACXX_HOST_DEVICE168 constexpr index_type __get_size(_CUDA_VSTD::extents<_SizeType, _Ep...>,_CUDA_VSTD::integer_sequence<size_t, _Idx...>) const {169 return __MDSPAN_FOLD_TIMES_RIGHT( static_cast<index_type>(extents().extent(_Idx)), 1 );170 }171 172 //----------------------------------------------------------------------------173 174 template <class>175 friend class mapping;176 177 //----------------------------------------------------------------------------178 179 // Workaround for non-deducibility of the index sequence template parameter if it's given at the top level180 template <class>181 struct __deduction_workaround;182 183 template <size_t... _Idxs>184 struct __deduction_workaround<_CUDA_VSTD::index_sequence<_Idxs...>>185 {186 template <class _OtherExtents>187 __MDSPAN_INLINE_FUNCTION188 static constexpr bool _eq_impl(mapping const& __self, mapping<_OtherExtents> const& __other) noexcept {189 return __MDSPAN_FOLD_AND((__self.stride(_Idxs) == __other.stride(_Idxs)) /* && ... */)190 && __MDSPAN_FOLD_AND((__self.extents().extent(_Idxs) == __other.extents().extent(_Idxs)) /* || ... */);191 }192 template <class _OtherExtents>193 __MDSPAN_INLINE_FUNCTION194 static constexpr bool _not_eq_impl(mapping const& __self, mapping<_OtherExtents> const& __other) noexcept {195 return __MDSPAN_FOLD_OR((__self.stride(_Idxs) != __other.stride(_Idxs)) /* || ... */)196 || __MDSPAN_FOLD_OR((__self.extents().extent(_Idxs) != __other.extents().extent(_Idxs)) /* || ... */);197 }198 199 template <class... _Integral>200 __MDSPAN_FORCE_INLINE_FUNCTION201 static constexpr size_t _call_op_impl(mapping const& __self, _Integral... __idxs) noexcept {202 return __MDSPAN_FOLD_PLUS_RIGHT((__idxs * __self.stride(_Idxs)), /* + ... + */ 0);203 }204 205 __MDSPAN_INLINE_FUNCTION206 static constexpr size_t _req_span_size_impl(mapping const& __self) noexcept {207 // assumes no negative strides; not sure if I'm allowed to assume that or not208 return __impl::_call_op_impl(__self, (__self.extents().template __extent<_Idxs>() - 1)...) + 1;209 }210 211 template<class _OtherMapping>212 __MDSPAN_INLINE_FUNCTION213 static constexpr const __strides_storage_t fill_strides(const _OtherMapping& __map) {214 return __strides_storage_t{static_cast<index_type>(__map.stride(_Idxs))...};215 }216 217 __MDSPAN_INLINE_FUNCTION218 static constexpr const __strides_storage_t& fill_strides(const __strides_storage_t& __s) {219 return __s;220 }221 222 template<class _IntegralType>223 __MDSPAN_INLINE_FUNCTION224 static constexpr const __strides_storage_t fill_strides(const _CUDA_VSTD::array<_IntegralType,extents_type::rank()>& __s) {225 return __strides_storage_t{static_cast<index_type>(__s[_Idxs])...};226 }227 228 template<class _IntegralType>229 __MDSPAN_INLINE_FUNCTION230 static constexpr const __strides_storage_t fill_strides(const _CUDA_VSTD::span<_IntegralType,extents_type::rank()>& __s) {231 return __strides_storage_t{static_cast<index_type>(__s[_Idxs])...};232 }233 234 __MDSPAN_INLINE_FUNCTION235 static constexpr const __strides_storage_t fill_strides(236 __detail::__extents_to_partially_static_sizes_t<237 _CUDA_VSTD::dextents<index_type, extents_type::rank()>>&& __s) {238 return __strides_storage_t{static_cast<index_type>(__s.template __get_n<_Idxs>())...};239 }240 241 template<size_t K>242 __MDSPAN_INLINE_FUNCTION243 static constexpr size_t __return_zero() { return 0; }244 245 template<class _Mapping>246 __MDSPAN_INLINE_FUNCTION247 static constexpr typename _Mapping::index_type248 __OFFSET(const _Mapping& m) { return m(__return_zero<_Idxs>()...); }249 };250 251 // Can't use defaulted parameter in the __deduction_workaround template because of a bug in MSVC warning C4348.252 using __impl = __deduction_workaround<_CUDA_VSTD::make_index_sequence<_Extents::rank()>>;253 254 255 //----------------------------------------------------------------------------256 257#ifndef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS258 __MDSPAN_INLINE_FUNCTION constexpr explicit259 mapping(__member_pair_t&& __m) : __members(_CUDA_VSTD::move(__m)) {}260#else261 __MDSPAN_INLINE_FUNCTION constexpr explicit262 mapping(__base_t&& __b) : __base_t(_CUDA_VSTD::move(__b)) {}263#endif264 265 public: // but not really266 __MDSPAN_INLINE_FUNCTION267 static constexpr mapping268 __make_mapping(269 __detail::__extents_to_partially_static_sizes_t<_Extents>&& __exts,270 __detail::__extents_to_partially_static_sizes_t<271 _CUDA_VSTD::dextents<index_type, _Extents::rank()>>&& __strs272 ) noexcept {273 // call the private constructor we created for this purpose274 return mapping(275#ifdef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS276 __base_t{277#endif278 __member_pair_t(279 extents_type::__make_extents_impl(_CUDA_VSTD::move(__exts)),280 __strides_storage_t{__impl::fill_strides(_CUDA_VSTD::move(__strs))}281 )282#ifdef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS283 }284#endif285 );286 }287 //----------------------------------------------------------------------------288 289 290 public:291 292 //--------------------------------------------------------------------------------293 294 __MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() noexcept = default;295 __MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping(mapping const&) noexcept = default;296 297 __MDSPAN_TEMPLATE_REQUIRES(298 class _IntegralTypes,299 /* requires */ (300 // MSVC 19.32 does not like using index_type here, requires the typename _Extents::index_type301 // error C2641: cannot deduce template arguments for '_CUDA_VSTD::layout_stride::mapping'302 _LIBCUDACXX_TRAIT(_CUDA_VSTD::is_convertible, const remove_const_t<_IntegralTypes>&, typename _Extents::index_type) &&303 _LIBCUDACXX_TRAIT(_CUDA_VSTD::is_nothrow_constructible, typename _Extents::index_type, const remove_const_t<_IntegralTypes>&)304 )305 )306 __MDSPAN_INLINE_FUNCTION307 constexpr308 mapping(309 extents_type const& __e,310 _CUDA_VSTD::array<_IntegralTypes, extents_type::rank()> const& __s311 ) noexcept312#ifndef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS313 : __members{314#else315 : __base_t(__base_t{__member_pair_t(316#endif317 __e, __strides_storage_t(__impl::fill_strides(__s))318#ifndef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS319 }320#else321 )})322#endif323 {324 /*325 * TODO: check preconditions326 * - __s[i] > 0 is true for all i in the range [0, rank_ ).327 * - REQUIRED-SPAN-SIZE(__e, __s) is a representable value of type index_type ([basic.fundamental]).328 * - If rank_ is greater than 0, then there exists a permutation P of the integers in the329 * range [0, rank_), such that __s[ pi ] >= __s[ pi − 1 ] * __e.extent( pi − 1 ) is true for330 * all i in the range [1, rank_ ), where pi is the ith element of P.331 */332 }333 334 __MDSPAN_TEMPLATE_REQUIRES(335 class _IntegralTypes,336 /* requires */ (337 // MSVC 19.32 does not like using index_type here, requires the typename _Extents::index_type338 // error C2641: cannot deduce template arguments for '_CUDA_VSTD::layout_stride::mapping'339 _LIBCUDACXX_TRAIT(_CUDA_VSTD::is_convertible, const remove_const_t<_IntegralTypes>&, typename _Extents::index_type) &&340 _LIBCUDACXX_TRAIT(_CUDA_VSTD::is_nothrow_constructible, typename _Extents::index_type, const remove_const_t<_IntegralTypes>&)341 )342 )343 __MDSPAN_INLINE_FUNCTION344 constexpr345 mapping(346 extents_type const& __e,347 _CUDA_VSTD::span<_IntegralTypes, extents_type::rank()> const& __s348 ) noexcept349#ifndef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS350 : __members{351#else352 : __base_t(__base_t{__member_pair_t(353#endif354 __e, __strides_storage_t(__impl::fill_strides(__s))355#ifndef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS356 }357#else358 )})359#endif360 {361 /*362 * TODO: check preconditions363 * - __s[i] > 0 is true for all i in the range [0, rank_ ).364 * - REQUIRED-SPAN-SIZE(__e, __s) is a representable value of type index_type ([basic.fundamental]).365 * - If rank_ is greater than 0, then there exists a permutation P of the integers in the366 * range [0, rank_), such that __s[ pi ] >= __s[ pi − 1 ] * __e.extent( pi − 1 ) is true for367 * all i in the range [1, rank_ ), where pi is the ith element of P.368 */369 }370 371#if !(__MDSPAN_USE_CONCEPTS && __MDSPAN_HAS_CXX_20)372 __MDSPAN_TEMPLATE_REQUIRES(373 class _StridedLayoutMapping,374 /* requires */ (375 _LIBCUDACXX_TRAIT(_CUDA_VSTD::is_constructible, extents_type, typename _StridedLayoutMapping::extents_type) &&376 __detail::__is_mapping_of<typename _StridedLayoutMapping::layout_type, _StridedLayoutMapping> &&377 _StridedLayoutMapping::is_always_unique() &&378 _StridedLayoutMapping::is_always_strided()379 )380 )381#else382 template<class _StridedLayoutMapping>383 requires(384 __detail::__layout_mapping_alike<_StridedLayoutMapping> &&385 _LIBCUDACXX_TRAIT(_CUDA_VSTD::is_constructible, extents_type, typename _StridedLayoutMapping::extents_type) &&386 _StridedLayoutMapping::is_always_unique() &&387 _StridedLayoutMapping::is_always_strided()388 )389#endif390 __MDSPAN_CONDITIONAL_EXPLICIT(391 (!_CUDA_VSTD::is_convertible<typename _StridedLayoutMapping::extents_type, extents_type>::value) &&392 (__detail::__is_mapping_of<layout_left, _StridedLayoutMapping> ||393 __detail::__is_mapping_of<layout_right, _StridedLayoutMapping> ||394 __detail::__is_mapping_of<layout_stride, _StridedLayoutMapping>)395 ) // needs two () due to comma396 __MDSPAN_INLINE_FUNCTION constexpr397 mapping(_StridedLayoutMapping const& __other) noexcept // NOLINT(google-explicit-constructor)398#ifndef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS399 : __members{400#else401 : __base_t(__base_t{__member_pair_t(402#endif403 __other.extents(), __strides_storage_t(__impl::fill_strides(__other))404#ifndef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS405 }406#else407 )})408#endif409 {410 /*411 * TODO: check preconditions412 * - __other.stride(i) > 0 is true for all i in the range [0, rank_ ).413 * - __other.required_span_size() is a representable value of type index_type ([basic.fundamental]).414 * - OFFSET(__other) == 0415 */416 }417 418 //--------------------------------------------------------------------------------419 420 __MDSPAN_INLINE_FUNCTION_DEFAULTED __MDSPAN_CONSTEXPR_14_DEFAULTED421 mapping& operator=(mapping const&) noexcept = default;422 423 __MDSPAN_INLINE_FUNCTION constexpr const extents_type& extents() const noexcept {424#ifndef _LIBCUDACXX_HAS_NO_ATTRIBUTE_NO_UNIQUE_ADDRESS425 return __members.__first();426#else427 return this->__base_t::__ref().__first();428#endif429 };430 431 __MDSPAN_INLINE_FUNCTION432 constexpr _CUDA_VSTD::array< index_type, extents_type::rank() > strides() const noexcept {433 return __strides_storage();434 }435 436 __MDSPAN_INLINE_FUNCTION437 constexpr index_type required_span_size() const noexcept {438 index_type __span_size = 1;439 for(unsigned __r = 0; __r < extents_type::rank(); __r++) {440 // Return early if any of the extents are zero441 if(extents().extent(__r)==0) return 0;442 __span_size += ( static_cast<index_type>(extents().extent(__r) - 1 ) * __strides_storage()[__r]);443 }444 return __span_size;445 }446 447 448 __MDSPAN_TEMPLATE_REQUIRES(449 class... _Indices,450 /* requires */ (451 sizeof...(_Indices) == _Extents::rank() &&452 __MDSPAN_FOLD_AND(_LIBCUDACXX_TRAIT(_CUDA_VSTD::is_convertible, _Indices, index_type) /*&& ...*/ ) &&453 __MDSPAN_FOLD_AND(_LIBCUDACXX_TRAIT(_CUDA_VSTD::is_nothrow_constructible, index_type, _Indices) /*&& ...*/)454 )455 )456 __MDSPAN_FORCE_INLINE_FUNCTION457 constexpr index_type operator()(_Indices... __idxs) const noexcept {458 // Should the op_impl operate in terms of `index_type` rather than `size_t`?459 // Casting `size_t` to `index_type` here.460 return static_cast<index_type>(__impl::_call_op_impl(*this, static_cast<index_type>(__idxs)...));461 }462 463 __MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; }464 __MDSPAN_INLINE_FUNCTION static constexpr bool is_always_exhaustive() noexcept {465 return false;466 }467 __MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; }468 469 __MDSPAN_INLINE_FUNCTION static constexpr bool is_unique() noexcept { return true; }470 __MDSPAN_INLINE_FUNCTION constexpr bool is_exhaustive() const noexcept {471 return required_span_size() == __get_size( extents(), _CUDA_VSTD::make_index_sequence<extents_type::rank()>());472 }473 __MDSPAN_INLINE_FUNCTION static constexpr bool is_strided() noexcept { return true; }474 475 476 __MDSPAN_TEMPLATE_REQUIRES(477 class _Ext = _Extents,478 /* requires */ (479 _Ext::rank() > 0480 )481 )482 __MDSPAN_INLINE_FUNCTION483 constexpr index_type stride(rank_type __r) const noexcept {484 return __strides_storage()[__r];485 }486 487#if !(__MDSPAN_USE_CONCEPTS && __MDSPAN_HAS_CXX_20)488 __MDSPAN_TEMPLATE_REQUIRES(489 class _StridedLayoutMapping,490 /* requires */ (491 __detail::__is_mapping_of<typename _StridedLayoutMapping::layout_type, _StridedLayoutMapping> &&492 (extents_type::rank() == _StridedLayoutMapping::extents_type::rank()) &&493 _StridedLayoutMapping::is_always_strided()494 )495 )496#else497 template<class _StridedLayoutMapping>498 requires(499 __detail::__layout_mapping_alike<_StridedLayoutMapping> &&500 (extents_type::rank() == _StridedLayoutMapping::extents_type::rank()) &&501 _StridedLayoutMapping::is_always_strided()502 )503#endif504 __MDSPAN_INLINE_FUNCTION505 friend constexpr bool operator==(const mapping& __x, const _StridedLayoutMapping& __y) noexcept {506 bool __strides_match = true;507 for(rank_type __r = 0; __r < extents_type::rank(); __r++)508 __strides_match = __strides_match && (__x.stride(__r) == __y.stride(__r));509 return (__x.extents() == __y.extents()) &&510 (__impl::__OFFSET(__y)== static_cast<typename _StridedLayoutMapping::index_type>(0)) &&511 __strides_match;512 }513 514 // This one is not technically part of the proposal. Just here to make implementation a bit more optimal hopefully515 __MDSPAN_TEMPLATE_REQUIRES(516 class _OtherExtents,517 /* requires */ (518 (extents_type::rank() == _OtherExtents::rank())519 )520 )521 __MDSPAN_INLINE_FUNCTION522 friend constexpr bool operator==(mapping const& __lhs, mapping<_OtherExtents> const& __rhs) noexcept {523 return __impl::_eq_impl(__lhs, __rhs);524 }525 526#if !__MDSPAN_HAS_CXX_20527 __MDSPAN_TEMPLATE_REQUIRES(528 class _StridedLayoutMapping,529 /* requires */ (530 __detail::__is_mapping_of<typename _StridedLayoutMapping::layout_type, _StridedLayoutMapping> &&531 (extents_type::rank() == _StridedLayoutMapping::extents_type::rank()) &&532 _StridedLayoutMapping::is_always_strided()533 )534 )535 __MDSPAN_INLINE_FUNCTION536 friend constexpr bool operator!=(const mapping& __x, const _StridedLayoutMapping& __y) noexcept {537 return not (__x == __y);538 }539 540 __MDSPAN_TEMPLATE_REQUIRES(541 class _OtherExtents,542 /* requires */ (543 (extents_type::rank() == _OtherExtents::rank())544 )545 )546 __MDSPAN_INLINE_FUNCTION547 friend constexpr bool operator!=(mapping const& __lhs, mapping<_OtherExtents> const& __rhs) noexcept {548 return __impl::_not_eq_impl(__lhs, __rhs);549 }550#endif551 552 };553};554 555#endif // _LIBCUDACXX_STD_VER > 11556 557_LIBCUDACXX_END_NAMESPACE_STD558 559#endif // _LIBCUDACXX___MDSPAN_LAYOUT_STRIDE_HPP560 