mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 22:06:36 +00:00
[libc++] mdspan - implement layout_stride (#69650)
This implements layout_stride for C++23 and with that completes the implementation of the C++23 mdspan header. The feature test macro is added, and the status pages updated. Co-authored-by: Damien L-G <dalg24@gmail.com> Differential Revision: https://reviews.llvm.org/D157171
This commit is contained in:
parent
2a32afddf5
commit
639a0986f3
@ -332,7 +332,7 @@ Status
|
||||
--------------------------------------------------- -----------------
|
||||
``__cpp_lib_is_scoped_enum`` ``202011L``
|
||||
--------------------------------------------------- -----------------
|
||||
``__cpp_lib_mdspan`` *unimplemented*
|
||||
``__cpp_lib_mdspan`` ``202207L``
|
||||
--------------------------------------------------- -----------------
|
||||
``__cpp_lib_move_only_function`` *unimplemented*
|
||||
--------------------------------------------------- -----------------
|
||||
|
@ -40,7 +40,6 @@ Paper Status
|
||||
|
||||
.. note::
|
||||
|
||||
.. [#note-P0009R18] P0009R18: ``extents``, ``dextents``, ``layout_left``, ``layout_right``, and ``default_accessor`` are implemented.
|
||||
.. [#note-P0533R9] P0533R9: ``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented.
|
||||
.. [#note-P1413R3] P1413R3: ``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but
|
||||
clang doesn't issue a diagnostic for deprecated using template declarations.
|
||||
|
@ -51,7 +51,7 @@
|
||||
"`P2442R1 <https://wg21.link/P2442R1>`__","LWG","Windowing range adaptors: ``views::chunk`` and ``views::slide``","February 2022","","","|ranges|"
|
||||
"`P2443R1 <https://wg21.link/P2443R1>`__","LWG","``views::chunk_by``","February 2022","|Complete|","18.0","|ranges|"
|
||||
"","","","","","",""
|
||||
"`P0009R18 <https://wg21.link/P0009R18>`__","LWG","mdspan: A Non-Owning Multidimensional Array Reference","July 2022","|In progress| [#note-P0009R18]_",""
|
||||
"`P0009R18 <https://wg21.link/P0009R18>`__","LWG","mdspan: A Non-Owning Multidimensional Array Reference","July 2022","|Complete|","18.0"
|
||||
"`P0429R9 <https://wg21.link/P0429R9>`__","LWG","A Standard ``flat_map``","July 2022","",""
|
||||
"`P1169R4 <https://wg21.link/P1169R4>`__","LWG","``static operator()``","July 2022","|Complete|","16.0"
|
||||
"`P1222R4 <https://wg21.link/P1222R4>`__","LWG","A Standard ``flat_set``","July 2022","",""
|
||||
@ -89,9 +89,9 @@
|
||||
"`P2549R1 <https://wg21.link/P2549R1>`__","LWG","``std::unexpected`` should have ``error()`` as member accessor","July 2022","|Complete|","16.0"
|
||||
"`P2585R0 <https://wg21.link/P2585R0>`__","LWG","Improving default container formatting","July 2022","|Complete|","17.0"
|
||||
"`P2590R2 <https://wg21.link/P2590R2>`__","LWG","Explicit lifetime management","July 2022","",""
|
||||
"`P2599R2 <https://wg21.link/P2599R2>`__","LWG","``mdspan::size_type`` should be ``index_type``","July 2022","",""
|
||||
"`P2604R0 <https://wg21.link/P2604R0>`__","LWG","mdspan: rename pointer and contiguous","July 2022","",""
|
||||
"`P2613R1 <https://wg21.link/P2613R1>`__","LWG","Add the missing ``empty`` to ``mdspan``","July 2022","",""
|
||||
"`P2599R2 <https://wg21.link/P2599R2>`__","LWG","``mdspan::size_type`` should be ``index_type``","July 2022","|Complete|","18.0"
|
||||
"`P2604R0 <https://wg21.link/P2604R0>`__","LWG","mdspan: rename pointer and contiguous","July 2022","|Complete|","18.0"
|
||||
"`P2613R1 <https://wg21.link/P2613R1>`__","LWG","Add the missing ``empty`` to ``mdspan``","July 2022","|Complete|","18.0"
|
||||
"","","","","","",""
|
||||
"`P1202R5 <https://wg21.link/P1202R5>`__","LWG", "Asymmetric Fences", "November 2022","","","|concurrency TS|"
|
||||
"`P1264R2 <https://wg21.link/P1264R2>`__","LWG", "Revising the wording of ``stream`` input operations", "November 2022","|Complete|","9.0",""
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -508,6 +508,7 @@ set(files
|
||||
__mdspan/extents.h
|
||||
__mdspan/layout_left.h
|
||||
__mdspan/layout_right.h
|
||||
__mdspan/layout_stride.h
|
||||
__mdspan/mdspan.h
|
||||
__memory/addressof.h
|
||||
__memory/align.h
|
||||
|
@ -42,14 +42,11 @@ struct layout_right {
|
||||
class mapping;
|
||||
};
|
||||
|
||||
/*
|
||||
// Will be implemented with follow on revision
|
||||
// Layout policy with a unique mapping where strides are arbitrary
|
||||
struct layout_stride {
|
||||
template<class Extents>
|
||||
class mapping;
|
||||
template <class _Extents>
|
||||
class mapping;
|
||||
};
|
||||
*/
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
|
@ -110,12 +110,27 @@ public:
|
||||
"layout_left::mapping converting ctor: other.required_span_size() must be representable as index_type.");
|
||||
}
|
||||
|
||||
// FIXME: add when we add other layouts
|
||||
# if 0
|
||||
template<class _OtherExtents>
|
||||
constexpr explicit(extents_type::rank() > 0)
|
||||
mapping(const layout_stride::mapping_<OtherExtents>&) noexcept;
|
||||
# endif
|
||||
template <class _OtherExtents>
|
||||
requires(is_constructible_v<extents_type, _OtherExtents>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(extents_type::rank() > 0)
|
||||
mapping(const layout_stride::mapping<_OtherExtents>& __other) noexcept
|
||||
: __extents_(__other.extents()) {
|
||||
if constexpr (extents_type::rank() > 0) {
|
||||
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
|
||||
([&]() {
|
||||
using _CommonType = common_type_t<typename extents_type::index_type, typename _OtherExtents::index_type>;
|
||||
for (rank_type __r = 0; __r < extents_type::rank(); __r++)
|
||||
if (static_cast<_CommonType>(stride(__r)) != static_cast<_CommonType>(__other.stride(__r)))
|
||||
return false;
|
||||
return true;
|
||||
}()),
|
||||
"layout_left::mapping from layout_stride ctor: strides are not compatible with layout_left.");
|
||||
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
|
||||
__mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
|
||||
"layout_left::mapping from layout_stride ctor: other.required_span_size() must be representable as "
|
||||
"index_type.");
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr mapping& operator=(const mapping&) noexcept = default;
|
||||
|
||||
|
@ -109,12 +109,27 @@ public:
|
||||
"layout_right::mapping converting ctor: other.required_span_size() must be representable as index_type.");
|
||||
}
|
||||
|
||||
// FIXME: add when we add other layouts
|
||||
# if 0
|
||||
template<class _OtherExtents>
|
||||
constexpr explicit(extents_type::rank() > 0)
|
||||
mapping(const layout_stride::mapping_<OtherExtents>&) noexcept;
|
||||
# endif
|
||||
template <class _OtherExtents>
|
||||
requires(is_constructible_v<extents_type, _OtherExtents>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(extents_type::rank() > 0)
|
||||
mapping(const layout_stride::mapping<_OtherExtents>& __other) noexcept
|
||||
: __extents_(__other.extents()) {
|
||||
if constexpr (extents_type::rank() > 0) {
|
||||
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
|
||||
([&]() {
|
||||
using _CommonType = common_type_t<typename extents_type::index_type, typename _OtherExtents::index_type>;
|
||||
for (rank_type __r = 0; __r < extents_type::rank(); __r++)
|
||||
if (static_cast<_CommonType>(stride(__r)) != static_cast<_CommonType>(__other.stride(__r)))
|
||||
return false;
|
||||
return true;
|
||||
}()),
|
||||
"layout_right::mapping from layout_stride ctor: strides are not compatible with layout_right.");
|
||||
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
|
||||
__mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
|
||||
"layout_right::mapping from layout_stride ctor: other.required_span_size() must be representable as "
|
||||
"index_type.");
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr mapping& operator=(const mapping&) noexcept = default;
|
||||
|
||||
|
366
libcxx/include/__mdspan/layout_stride.h
Normal file
366
libcxx/include/__mdspan/layout_stride.h
Normal file
@ -0,0 +1,366 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___MDSPAN_LAYOUT_STRIDE_H
|
||||
#define _LIBCPP___MDSPAN_LAYOUT_STRIDE_H
|
||||
|
||||
#include <__assert>
|
||||
#include <__config>
|
||||
#include <__fwd/mdspan.h>
|
||||
#include <__mdspan/extents.h>
|
||||
#include <__type_traits/is_constructible.h>
|
||||
#include <__type_traits/is_convertible.h>
|
||||
#include <__type_traits/is_nothrow_constructible.h>
|
||||
#include <__utility/as_const.h>
|
||||
#include <__utility/integer_sequence.h>
|
||||
#include <__utility/swap.h>
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
namespace __mdspan_detail {
|
||||
template <class _Layout, class _Mapping>
|
||||
constexpr bool __is_mapping_of =
|
||||
is_same_v<typename _Layout::template mapping<typename _Mapping::extents_type>, _Mapping>;
|
||||
|
||||
template <class _Mapping>
|
||||
concept __layout_mapping_alike = requires {
|
||||
requires __is_mapping_of<typename _Mapping::layout_type, _Mapping>;
|
||||
requires __is_extents_v<typename _Mapping::extents_type>;
|
||||
{ _Mapping::is_always_strided() } -> same_as<bool>;
|
||||
{ _Mapping::is_always_exhaustive() } -> same_as<bool>;
|
||||
{ _Mapping::is_always_unique() } -> same_as<bool>;
|
||||
bool_constant<_Mapping::is_always_strided()>::value;
|
||||
bool_constant<_Mapping::is_always_exhaustive()>::value;
|
||||
bool_constant<_Mapping::is_always_unique()>::value;
|
||||
};
|
||||
} // namespace __mdspan_detail
|
||||
|
||||
template <class _Extents>
|
||||
class layout_stride::mapping {
|
||||
public:
|
||||
static_assert(__mdspan_detail::__is_extents<_Extents>::value,
|
||||
"layout_stride::mapping template argument must be a specialization of extents.");
|
||||
|
||||
using extents_type = _Extents;
|
||||
using index_type = typename extents_type::index_type;
|
||||
using size_type = typename extents_type::size_type;
|
||||
using rank_type = typename extents_type::rank_type;
|
||||
using layout_type = layout_stride;
|
||||
|
||||
private:
|
||||
static constexpr rank_type __rank_ = extents_type::rank();
|
||||
|
||||
// Used for default construction check and mandates
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool __required_span_size_is_representable(const extents_type& __ext) {
|
||||
if constexpr (__rank_ == 0)
|
||||
return true;
|
||||
|
||||
index_type __prod = __ext.extent(0);
|
||||
for (rank_type __r = 1; __r < __rank_; __r++) {
|
||||
bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), &__prod);
|
||||
if (__overflowed)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class _OtherIndexType>
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool
|
||||
__required_span_size_is_representable(const extents_type& __ext, span<_OtherIndexType, __rank_> __strides) {
|
||||
if constexpr (__rank_ == 0)
|
||||
return true;
|
||||
|
||||
index_type __size = 1;
|
||||
for (rank_type __r = 0; __r < __rank_; __r++) {
|
||||
// We can only check correct conversion of _OtherIndexType if it is an integral
|
||||
if constexpr (is_integral_v<_OtherIndexType>) {
|
||||
using _CommonType = common_type_t<index_type, _OtherIndexType>;
|
||||
if (static_cast<_CommonType>(__strides[__r]) > static_cast<_CommonType>(numeric_limits<index_type>::max()))
|
||||
return false;
|
||||
}
|
||||
if (__ext.extent(__r) == static_cast<index_type>(0))
|
||||
return true;
|
||||
index_type __prod = (__ext.extent(__r) - 1);
|
||||
bool __overflowed_mul = __builtin_mul_overflow(__prod, static_cast<index_type>(__strides[__r]), &__prod);
|
||||
if (__overflowed_mul)
|
||||
return false;
|
||||
bool __overflowed_add = __builtin_add_overflow(__size, __prod, &__size);
|
||||
if (__overflowed_add)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// compute offset of a strided layout mapping
|
||||
template <class _StridedMapping>
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr index_type __offset(const _StridedMapping& __mapping) {
|
||||
if constexpr (_StridedMapping::extents_type::rank() == 0) {
|
||||
return static_cast<index_type>(__mapping());
|
||||
} else if (__mapping.required_span_size() == static_cast<typename _StridedMapping::index_type>(0)) {
|
||||
return static_cast<index_type>(0);
|
||||
} else {
|
||||
return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
|
||||
return static_cast<index_type>(__mapping((_Pos ? 0 : 0)...));
|
||||
}(make_index_sequence<__rank_>());
|
||||
}
|
||||
}
|
||||
|
||||
// compute the permutation for sorting the stride array
|
||||
// we never actually sort the stride array
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __bubble_sort_by_strides(array<rank_type, __rank_>& __permute) const {
|
||||
for (rank_type __i = __rank_ - 1; __i > 0; __i--) {
|
||||
for (rank_type __r = 0; __r < __i; __r++) {
|
||||
if (__strides_[__permute[__r]] > __strides_[__permute[__r + 1]]) {
|
||||
swap(__permute[__r], __permute[__r + 1]);
|
||||
} else {
|
||||
// if two strides are the same then one of the associated extents must be 1 or 0
|
||||
// both could be, but you can't have one larger than 1 come first
|
||||
if ((__strides_[__permute[__r]] == __strides_[__permute[__r + 1]]) &&
|
||||
(__extents_.extent(__permute[__r]) > static_cast<index_type>(1)))
|
||||
swap(__permute[__r], __permute[__r + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static_assert((extents_type::rank_dynamic() > 0) || __required_span_size_is_representable(extents_type()),
|
||||
"layout_stride::mapping product of static extents must be representable as index_type.");
|
||||
|
||||
public:
|
||||
// [mdspan.layout.stride.cons], constructors
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr mapping() noexcept : __extents_(extents_type()) {
|
||||
// Note the nominal precondition is covered by above static assert since
|
||||
// if rank_dynamic is != 0 required_span_size is zero for default construction
|
||||
if constexpr (__rank_ > 0) {
|
||||
index_type __stride = 1;
|
||||
for (rank_type __r = __rank_ - 1; __r > static_cast<rank_type>(0); __r--) {
|
||||
__strides_[__r] = __stride;
|
||||
__stride *= __extents_.extent(__r);
|
||||
}
|
||||
__strides_[0] = __stride;
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr mapping(const mapping&) noexcept = default;
|
||||
|
||||
template <class _OtherIndexType>
|
||||
requires(is_convertible_v<const _OtherIndexType&, index_type> &&
|
||||
is_nothrow_constructible_v<index_type, const _OtherIndexType&>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext, span<_OtherIndexType, __rank_> __strides) noexcept
|
||||
: __extents_(__ext), __strides_([&]<size_t... _Pos>(index_sequence<_Pos...>) {
|
||||
return __mdspan_detail::__possibly_empty_array<index_type, __rank_>{
|
||||
static_cast<index_type>(std::as_const(__strides[_Pos]))...};
|
||||
}(make_index_sequence<__rank_>())) {
|
||||
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
|
||||
([&]<size_t... _Pos>(index_sequence<_Pos...>) {
|
||||
// For integrals we can do a pre-conversion check, for other types not
|
||||
if constexpr (is_integral_v<_OtherIndexType>) {
|
||||
return ((__strides[_Pos] > static_cast<_OtherIndexType>(0)) && ... && true);
|
||||
} else {
|
||||
return ((static_cast<index_type>(__strides[_Pos]) > static_cast<index_type>(0)) && ... && true);
|
||||
}
|
||||
}(make_index_sequence<__rank_>())),
|
||||
"layout_stride::mapping ctor: all strides must be greater than 0");
|
||||
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
|
||||
__required_span_size_is_representable(__ext, __strides),
|
||||
"layout_stride::mapping ctor: required span size is not representable as index_type.");
|
||||
if constexpr (__rank_ > 1) {
|
||||
_LIBCPP_ASSERT_UNCATEGORIZED(
|
||||
([&]<size_t... _Pos>(index_sequence<_Pos...>) {
|
||||
// basically sort the dimensions based on strides and extents, sorting is represented in permute array
|
||||
array<rank_type, __rank_> __permute{_Pos...};
|
||||
__bubble_sort_by_strides(__permute);
|
||||
|
||||
// check that this permutations represents a growing set
|
||||
for (rank_type __i = 1; __i < __rank_; __i++)
|
||||
if (static_cast<index_type>(__strides[__permute[__i]]) <
|
||||
static_cast<index_type>(__strides[__permute[__i - 1]]) * __extents_.extent(__permute[__i - 1]))
|
||||
return false;
|
||||
return true;
|
||||
}(make_index_sequence<__rank_>())),
|
||||
"layout_stride::mapping ctor: the provided extents and strides lead to a non-unique mapping");
|
||||
}
|
||||
}
|
||||
|
||||
template <class _OtherIndexType>
|
||||
requires(is_convertible_v<const _OtherIndexType&, index_type> &&
|
||||
is_nothrow_constructible_v<index_type, const _OtherIndexType&>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext,
|
||||
const array<_OtherIndexType, __rank_>& __strides) noexcept
|
||||
: mapping(__ext, span(__strides)) {}
|
||||
|
||||
template <class _StridedLayoutMapping>
|
||||
requires(__mdspan_detail::__layout_mapping_alike<_StridedLayoutMapping> &&
|
||||
is_constructible_v<extents_type, typename _StridedLayoutMapping::extents_type> &&
|
||||
_StridedLayoutMapping::is_always_unique() && _StridedLayoutMapping::is_always_strided())
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(
|
||||
!(is_convertible_v<typename _StridedLayoutMapping::extents_type, extents_type> &&
|
||||
(__mdspan_detail::__is_mapping_of<layout_left, _StridedLayoutMapping> ||
|
||||
__mdspan_detail::__is_mapping_of<layout_right, _StridedLayoutMapping> ||
|
||||
__mdspan_detail::__is_mapping_of<layout_stride, _StridedLayoutMapping>)))
|
||||
mapping(const _StridedLayoutMapping& __other) noexcept
|
||||
: __extents_(__other.extents()), __strides_([&]<size_t... _Pos>(index_sequence<_Pos...>) {
|
||||
// stride() only compiles for rank > 0
|
||||
if constexpr (__rank_ > 0) {
|
||||
return __mdspan_detail::__possibly_empty_array<index_type, __rank_>{
|
||||
static_cast<index_type>(__other.stride(_Pos))...};
|
||||
} else {
|
||||
return __mdspan_detail::__possibly_empty_array<index_type, 0>{};
|
||||
}
|
||||
}(make_index_sequence<__rank_>())) {
|
||||
// stride() only compiles for rank > 0
|
||||
if constexpr (__rank_ > 0) {
|
||||
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
|
||||
([&]<size_t... _Pos>(index_sequence<_Pos...>) {
|
||||
return ((static_cast<index_type>(__other.stride(_Pos)) > static_cast<index_type>(0)) && ... && true);
|
||||
}(make_index_sequence<__rank_>())),
|
||||
"layout_stride::mapping converting ctor: all strides must be greater than 0");
|
||||
}
|
||||
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
|
||||
__mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
|
||||
"layout_stride::mapping converting ctor: other.required_span_size() must be representable as index_type.");
|
||||
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(static_cast<index_type>(0) == __offset(__other),
|
||||
"layout_stride::mapping converting ctor: base offset of mapping must be zero.");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr mapping& operator=(const mapping&) noexcept = default;
|
||||
|
||||
// [mdspan.layout.stride.obs], observers
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const extents_type& extents() const noexcept { return __extents_; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr array<index_type, __rank_> strides() const noexcept {
|
||||
return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
|
||||
return array<index_type, __rank_>{__strides_[_Pos]...};
|
||||
}(make_index_sequence<__rank_>());
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr index_type required_span_size() const noexcept {
|
||||
if constexpr (__rank_ == 0) {
|
||||
return static_cast<index_type>(1);
|
||||
} else {
|
||||
return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
|
||||
if ((__extents_.extent(_Pos) * ... * 1) == 0)
|
||||
return static_cast<index_type>(0);
|
||||
else
|
||||
return static_cast<index_type>(
|
||||
static_cast<index_type>(1) +
|
||||
(((__extents_.extent(_Pos) - static_cast<index_type>(1)) * __strides_[_Pos]) + ... +
|
||||
static_cast<index_type>(0)));
|
||||
}(make_index_sequence<__rank_>());
|
||||
}
|
||||
}
|
||||
|
||||
template <class... _Indices>
|
||||
requires((sizeof...(_Indices) == __rank_) && (is_convertible_v<_Indices, index_type> && ...) &&
|
||||
(is_nothrow_constructible_v<index_type, _Indices> && ...))
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr index_type operator()(_Indices... __idx) const noexcept {
|
||||
// Mappings are generally meant to be used for accessing allocations and are meant to guarantee to never
|
||||
// return a value exceeding required_span_size(), which is used to know how large an allocation one needs
|
||||
// Thus, this is a canonical point in multi-dimensional data structures to make invalid element access checks
|
||||
// However, mdspan does check this on its own, so for now we avoid double checking in hardened mode
|
||||
_LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__is_multidimensional_index_in(__extents_, __idx...),
|
||||
"layout_stride::mapping: out of bounds indexing");
|
||||
return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
|
||||
return ((static_cast<index_type>(__idx) * __strides_[_Pos]) + ... + index_type(0));
|
||||
}(make_index_sequence<sizeof...(_Indices)>());
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept { return true; }
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept { return false; }
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept { return true; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_unique() noexcept { return true; }
|
||||
// The answer of this function is fairly complex in the case where one or more
|
||||
// extents are zero.
|
||||
// Technically it is meaningless to query is_exhaustive() in that case, but unfortunately
|
||||
// the way the standard defines this function, we can't give a simple true or false then.
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool is_exhaustive() const noexcept {
|
||||
if constexpr (__rank_ == 0)
|
||||
return true;
|
||||
else {
|
||||
index_type __span_size = required_span_size();
|
||||
if (__span_size == static_cast<index_type>(0)) {
|
||||
if constexpr (__rank_ == 1)
|
||||
return __strides_[0] == 1;
|
||||
else {
|
||||
rank_type __r_largest = 0;
|
||||
for (rank_type __r = 1; __r < __rank_; __r++)
|
||||
if (__strides_[__r] > __strides_[__r_largest])
|
||||
__r_largest = __r;
|
||||
for (rank_type __r = 0; __r < __rank_; __r++)
|
||||
if (__extents_.extent(__r) == 0 && __r != __r_largest)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return required_span_size() == [&]<size_t... _Pos>(index_sequence<_Pos...>) {
|
||||
return (__extents_.extent(_Pos) * ... * static_cast<index_type>(1));
|
||||
}(make_index_sequence<__rank_>());
|
||||
}
|
||||
}
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_strided() noexcept { return true; }
|
||||
|
||||
// according to the standard layout_stride does not have a constraint on stride(r) for rank>0
|
||||
// it still has the precondition though
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const noexcept {
|
||||
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__r < __rank_, "layout_stride::mapping::stride(): invalid rank index");
|
||||
return __strides_[__r];
|
||||
}
|
||||
|
||||
template <class _OtherMapping>
|
||||
requires(__mdspan_detail::__layout_mapping_alike<_OtherMapping> &&
|
||||
(_OtherMapping::extents_type::rank() == __rank_) && _OtherMapping::is_always_strided())
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const mapping& __lhs, const _OtherMapping& __rhs) noexcept {
|
||||
if (__offset(__rhs))
|
||||
return false;
|
||||
if constexpr (__rank_ == 0)
|
||||
return true;
|
||||
else {
|
||||
return __lhs.extents() == __rhs.extents() && [&]<size_t... _Pos>(index_sequence<_Pos...>) {
|
||||
// avoid warning when comparing signed and unsigner integers and pick the wider of two types
|
||||
using _CommonType = common_type_t<index_type, typename _OtherMapping::index_type>;
|
||||
return ((static_cast<_CommonType>(__lhs.stride(_Pos)) == static_cast<_CommonType>(__rhs.stride(_Pos))) && ... &&
|
||||
true);
|
||||
}(make_index_sequence<__rank_>());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS extents_type __extents_{};
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS __mdspan_detail::__possibly_empty_array<index_type, __rank_> __strides_{};
|
||||
};
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___MDSPAN_LAYOUT_STRIDE_H
|
@ -190,6 +190,63 @@ namespace std {
|
||||
};
|
||||
}
|
||||
|
||||
// layout_stride synopsis
|
||||
|
||||
namespace std {
|
||||
template<class Extents>
|
||||
class layout_stride::mapping {
|
||||
public:
|
||||
using extents_type = Extents;
|
||||
using index_type = typename extents_type::index_type;
|
||||
using size_type = typename extents_type::size_type;
|
||||
using rank_type = typename extents_type::rank_type;
|
||||
using layout_type = layout_stride;
|
||||
|
||||
private:
|
||||
static constexpr rank_type rank_ = extents_type::rank(); // exposition only
|
||||
|
||||
public:
|
||||
// [mdspan.layout.stride.cons], constructors
|
||||
constexpr mapping() noexcept;
|
||||
constexpr mapping(const mapping&) noexcept = default;
|
||||
template<class OtherIndexType>
|
||||
constexpr mapping(const extents_type&, span<OtherIndexType, rank_>) noexcept;
|
||||
template<class OtherIndexType>
|
||||
constexpr mapping(const extents_type&, const array<OtherIndexType, rank_>&) noexcept;
|
||||
|
||||
template<class StridedLayoutMapping>
|
||||
constexpr explicit(see below) mapping(const StridedLayoutMapping&) noexcept;
|
||||
|
||||
constexpr mapping& operator=(const mapping&) noexcept = default;
|
||||
|
||||
// [mdspan.layout.stride.obs], observers
|
||||
constexpr const extents_type& extents() const noexcept { return extents_; }
|
||||
constexpr array<index_type, rank_> strides() const noexcept { return strides_; }
|
||||
|
||||
constexpr index_type required_span_size() const noexcept;
|
||||
|
||||
template<class... Indices>
|
||||
constexpr index_type operator()(Indices...) const noexcept;
|
||||
|
||||
static constexpr bool is_always_unique() noexcept { return true; }
|
||||
static constexpr bool is_always_exhaustive() noexcept { return false; }
|
||||
static constexpr bool is_always_strided() noexcept { return true; }
|
||||
|
||||
static constexpr bool is_unique() noexcept { return true; }
|
||||
constexpr bool is_exhaustive() const noexcept;
|
||||
static constexpr bool is_strided() noexcept { return true; }
|
||||
|
||||
constexpr index_type stride(rank_type i) const noexcept { return strides_[i]; }
|
||||
|
||||
template<class OtherMapping>
|
||||
friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;
|
||||
|
||||
private:
|
||||
extents_type extents_{}; // exposition only
|
||||
array<index_type, rank_> strides_{}; // exposition only
|
||||
};
|
||||
}
|
||||
|
||||
// default_accessor synopsis
|
||||
|
||||
namespace std {
|
||||
@ -348,7 +405,9 @@ namespace std {
|
||||
#include <__mdspan/extents.h>
|
||||
#include <__mdspan/layout_left.h>
|
||||
#include <__mdspan/layout_right.h>
|
||||
#include <__mdspan/layout_stride.h>
|
||||
#include <__mdspan/mdspan.h>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
@ -1510,6 +1510,7 @@ module std_private_mdspan_extents [system] {
|
||||
}
|
||||
module std_private_mdspan_layout_left [system] { header "__mdspan/layout_left.h" }
|
||||
module std_private_mdspan_layout_right [system] { header "__mdspan/layout_right.h" }
|
||||
module std_private_mdspan_layout_stride [system] { header "__mdspan/layout_stride.h" }
|
||||
module std_private_mdspan_mdspan [system] { header "__mdspan/mdspan.h" }
|
||||
module std_private_mdspan_mdspan_fwd [system] { header "__fwd/mdspan.h" }
|
||||
|
||||
|
@ -427,7 +427,7 @@ __cpp_lib_within_lifetime 202306L <type_traits>
|
||||
# define __cpp_lib_forward_like 202207L
|
||||
# define __cpp_lib_invoke_r 202106L
|
||||
# define __cpp_lib_is_scoped_enum 202011L
|
||||
// # define __cpp_lib_mdspan 202207L
|
||||
# define __cpp_lib_mdspan 202207L
|
||||
// # define __cpp_lib_move_only_function 202110L
|
||||
# undef __cpp_lib_optional
|
||||
# define __cpp_lib_optional 202110L
|
||||
|
@ -18,7 +18,7 @@ export namespace std {
|
||||
// [mdspan.layout], layout mapping
|
||||
using std::layout_left;
|
||||
using std::layout_right;
|
||||
// using std::layout_stride;
|
||||
using std::layout_stride;
|
||||
|
||||
// [mdspan.accessor.default], class template default_accessor
|
||||
using std::default_accessor;
|
||||
|
@ -0,0 +1,83 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// UNSUPPORTED: libcpp-hardening-mode=unchecked
|
||||
// XFAIL: availability-verbose_abort-missing
|
||||
// ADDITIONAL_COMPILE_FLAGS: -Wno-ctad-maybe-unsupported
|
||||
|
||||
// FIXME: https://github.com/llvm/llvm-project/issues/64719
|
||||
// There appear to be some issues around ctad which make it
|
||||
// currently impossible to get this code warning free.
|
||||
// Thus added the additional compile flag above
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class OtherExtents>
|
||||
// constexpr explicit(extents_type::rank() > 0)
|
||||
// mapping(const layout_stride::mapping<OtherExtents>& other);
|
||||
//
|
||||
// Constraints: is_constructible_v<extents_type, OtherExtents> is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// - If extents_type::rank() > 0 is true, then for all r in the range [0, extents_type::rank()),
|
||||
// other.stride(r) equals other.extents().fwd-prod-of-extents(r), and
|
||||
// - other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with other.extents().
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
// working case
|
||||
{
|
||||
std::layout_stride::mapping arg(std::extents<int, D>(5), std::array<int, 1>{1});
|
||||
[[maybe_unused]] std::layout_left::mapping<std::extents<size_t, 5>> m(arg); // should work
|
||||
}
|
||||
// mismatch of static extent
|
||||
{
|
||||
std::layout_stride::mapping arg(std::extents<int, D>(5), std::array<int, 1>{1});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_left::mapping<std::extents<int, 3>> m(arg); }()),
|
||||
"extents construction: mismatch of provided arguments with static extents.");
|
||||
}
|
||||
// non-representability of extents itself
|
||||
{
|
||||
std::layout_stride::mapping arg(std::extents<int, D>(500), std::array<int, 1>{1});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_left::mapping<std::extents<char, D>> m(arg); }()),
|
||||
"extents ctor: arguments must be representable as index_type and nonnegative");
|
||||
}
|
||||
// non-representability of required span size
|
||||
{
|
||||
std::layout_stride::mapping arg(std::extents<int, D, D>(100, 3), std::array<int, 2>{1, 100});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] { std::layout_left::mapping<std::extents<char, D, D>> m(arg); }()),
|
||||
"layout_left::mapping from layout_stride ctor: other.required_span_size() must be "
|
||||
"representable as index_type.");
|
||||
}
|
||||
// strides are not layout_left compatible
|
||||
{
|
||||
std::layout_stride::mapping arg(std::extents<int, D>(5), std::array<int, 1>{2});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] { std::layout_left::mapping<std::extents<size_t, 5>> m(arg); }()),
|
||||
"layout_left::mapping from layout_stride ctor: strides are not compatible with layout_left.");
|
||||
}
|
||||
{
|
||||
std::layout_stride::mapping arg(std::extents<int, D, D>(100, 3), std::array<int, 2>{2, 200});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] { std::layout_left::mapping<std::extents<int, D, D>> m(arg); }()),
|
||||
"layout_left::mapping from layout_stride ctor: strides are not compatible with layout_left.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// UNSUPPORTED: libcpp-hardening-mode=unchecked
|
||||
// XFAIL: availability-verbose_abort-missing
|
||||
// ADDITIONAL_COMPILE_FLAGS: -Wno-ctad-maybe-unsupported
|
||||
|
||||
// FIXME: https://github.com/llvm/llvm-project/issues/64719
|
||||
// There appear to be some issues around ctad which make it
|
||||
// currently impossible to get this code warning free.
|
||||
// Thus added the additional compile flag above
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class OtherExtents>
|
||||
// constexpr explicit(extents_type::rank() > 0)
|
||||
// mapping(const layout_stride::mapping<OtherExtents>& other);
|
||||
//
|
||||
// Constraints: is_constructible_v<extents_type, OtherExtents> is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// - If extents_type::rank() > 0 is true, then for all r in the range [0, extents_type::rank()),
|
||||
// other.stride(r) equals other.extents().fwd-prod-of-extents(r), and
|
||||
// - other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with other.extents().
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
// working case
|
||||
{
|
||||
std::layout_stride::mapping arg(std::extents<int, D>(5), std::array<int, 1>{1});
|
||||
[[maybe_unused]] std::layout_right::mapping<std::extents<size_t, 5>> m(arg); // should work
|
||||
}
|
||||
// mismatch of static extent
|
||||
{
|
||||
std::layout_stride::mapping arg(std::extents<int, D>(5), std::array<int, 1>{1});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_right::mapping<std::extents<int, 3>> m(arg); }()),
|
||||
"extents construction: mismatch of provided arguments with static extents.");
|
||||
}
|
||||
// non-representability of extents itself
|
||||
{
|
||||
std::layout_stride::mapping arg(std::extents<int, D>(500), std::array<int, 1>{1});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_right::mapping<std::extents<char, D>> m(arg); }()),
|
||||
"extents ctor: arguments must be representable as index_type and nonnegative");
|
||||
}
|
||||
// non-representability of required span size
|
||||
{
|
||||
std::layout_stride::mapping arg(std::extents<int, D, D>(100, 3), std::array<int, 2>{3, 1});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] { std::layout_right::mapping<std::extents<char, D, D>> m(arg); }()),
|
||||
"layout_right::mapping from layout_stride ctor: other.required_span_size() must be "
|
||||
"representable as index_type.");
|
||||
}
|
||||
// strides are not layout_right compatible
|
||||
{
|
||||
std::layout_stride::mapping arg(std::extents<int, D>(5), std::array<int, 1>{2});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] { std::layout_right::mapping<std::extents<size_t, 5>> m(arg); }()),
|
||||
"layout_right::mapping from layout_stride ctor: strides are not compatible with layout_right.");
|
||||
}
|
||||
{
|
||||
std::layout_stride::mapping arg(std::extents<int, D, D>(100, 3), std::array<int, 2>{6, 2});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] { std::layout_right::mapping<std::extents<int, D, D>> m(arg); }()),
|
||||
"layout_right::mapping from layout_stride ctor: strides are not compatible with layout_right.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// UNSUPPORTED: libcpp-hardening-mode=unchecked
|
||||
// XFAIL: availability-verbose_abort-missing
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class StridedLayoutMapping>
|
||||
// constexpr explicit(see below)
|
||||
// mapping(const StridedLayoutMapping& other) noexcept;
|
||||
//
|
||||
// Constraints:
|
||||
// - layout-mapping-alike<StridedLayoutMapping> is satisfied.
|
||||
// - is_constructible_v<extents_type, typename StridedLayoutMapping::extents_type> is true.
|
||||
// - StridedLayoutMapping::is_always_unique() is true.
|
||||
// - StridedLayoutMapping::is_always_strided() is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// - StridedLayoutMapping meets the layout mapping requirements ([mdspan.layout.policy.reqmts]),
|
||||
// - other.stride(r) > 0 is true for every rank index r of extents(),
|
||||
// - other.required_span_size() is representable as a value of type index_type ([basic.fundamental]), and
|
||||
// - OFFSET(other) == 0 is true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with other.extents(), and for all d in the range [0, rank_),
|
||||
// direct-non-list-initializes strides_[d] with other.stride(d).
|
||||
//
|
||||
// Remarks: The expression inside explicit is equivalent to:
|
||||
// - !(is_convertible_v<typename StridedLayoutMapping::extents_type, extents_type> &&
|
||||
// (is-mapping-of<layout_left, LayoutStrideMapping> ||
|
||||
// is-mapping-of<layout_right, LayoutStrideMapping> ||
|
||||
// is-mapping-of<layout_stride, LayoutStrideMapping>))
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
|
||||
#include "check_assertion.h"
|
||||
#include "../../../../../std/containers/views/mdspan/CustomTestLayouts.h"
|
||||
|
||||
int main(int, char**) {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
// working case
|
||||
{
|
||||
std::extents<int, D, D> arg_exts{100, 5};
|
||||
std::layout_stride::mapping<std::extents<int, D, D>> arg(arg_exts, std::array<int, 2>{1, 100});
|
||||
[[maybe_unused]] std::layout_stride::mapping<std::extents<size_t, D, 5>> m(arg); // should work
|
||||
}
|
||||
// mismatch of static extent
|
||||
{
|
||||
std::extents<int, D, D> arg_exts{100, 5};
|
||||
std::layout_stride::mapping<std::extents<int, D, D>> arg(arg_exts, std::array<int, 2>{1, 100});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_stride::mapping<std::extents<int, D, 3>> m(arg); }()),
|
||||
"extents construction: mismatch of provided arguments with static extents.");
|
||||
}
|
||||
// non-representability of extents itself
|
||||
{
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::layout_stride::mapping<std::extents<char, D>> m(
|
||||
std::layout_stride::mapping<std::extents<int, D>>(std::extents<int, D>(500), std::array<int, 1>{1}));
|
||||
}()),
|
||||
"extents ctor: arguments must be representable as index_type and nonnegative");
|
||||
}
|
||||
// all strides must be larger than zero
|
||||
{
|
||||
always_convertible_layout::mapping<std::dextents<int, 2>> offset_map(std::dextents<int, 2>{10, 10}, 100, -1);
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] { std::layout_stride::template mapping<std::extents<char, D, D>> m(offset_map); }()),
|
||||
"layout_stride::mapping converting ctor: all strides must be greater than 0");
|
||||
}
|
||||
// required_span_size not representable, while individual extents are
|
||||
{
|
||||
std::extents<int, D, D> arg_exts{100, 5};
|
||||
std::layout_stride::mapping<std::extents<int, D, D>> arg(arg_exts, std::array<int, 2>{1, 100});
|
||||
// check extents would be constructible
|
||||
[[maybe_unused]] std::extents<char, D, 5> e(arg_exts);
|
||||
// but the product is not, so we can't use it for layout_stride
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] { std::layout_stride::template mapping<std::extents<char, D, 5>> m(arg); }()),
|
||||
"layout_stride::mapping converting ctor: other.required_span_size() must be representable as index_type.");
|
||||
}
|
||||
// required_span_size not representable, while individual extents are, edge case
|
||||
{
|
||||
// required span size = (3-1)*50 + (10-1) * 3 + 1 = 128
|
||||
std::extents<int, D, D> arg_exts{3, 10};
|
||||
std::layout_stride::mapping<std::extents<int, D, D>> arg(arg_exts, std::array<int, 2>{50, 3});
|
||||
// sanity check:
|
||||
assert(arg.required_span_size() == 128);
|
||||
// check extents would be constructible
|
||||
[[maybe_unused]] std::extents<signed char, D, 10> e(arg_exts);
|
||||
// but the product is not, so we can't use it for layout_stride
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] { std::layout_stride::template mapping<std::extents<signed char, D, 10>> m(arg); }()),
|
||||
"layout_stride::mapping converting ctor: other.required_span_size() must be representable as index_type.");
|
||||
}
|
||||
// base offset must be 0 (i.e. mapping(0,...,0)==0) for a strided layout with positiv strides
|
||||
{
|
||||
always_convertible_layout::mapping<std::dextents<int, 2>> offset_map(std::dextents<int, 2>{10, 10}, 3);
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] { std::layout_stride::template mapping<std::extents<char, D, D>> m(offset_map); }()),
|
||||
"layout_stride::mapping converting ctor: base offset of mapping must be zero.");
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// UNSUPPORTED: !libcpp-hardening-mode=debug
|
||||
// XFAIL: availability-verbose_abort-missing
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class OtherIndexType>
|
||||
// constexpr mapping(const extents_type& e, const array<OtherIndexType, rank_>& s) noexcept;
|
||||
//
|
||||
// Constraints:
|
||||
// - is_convertible_v<const OtherIndexType&, index_type> is true, and
|
||||
// - is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// - s[i] > 0 is true for all i in the range [0, rank_).
|
||||
// - REQUIRED-SPAN-SIZE(e, s) is representable as a value of type index_type ([basic.fundamental]).
|
||||
// - If rank_ is greater than 0, then there exists a permutation P of the integers in the range [0, rank_),
|
||||
// such that s[pi] >= s[pi_1] * e.extent(pi_1) is true for all i in the range [1, rank_), where
|
||||
// pi is the ith element of P.
|
||||
// [Note 1: For layout_stride, this condition is necessary and sufficient for is_unique() to be true. end note]
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with e, and for all d in the range [0, rank_), direct-non-list-initializes strides_[d] with as_const(s[d]).
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
// overlapping strides
|
||||
{
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::layout_stride::template mapping<std::extents<unsigned, D, 5, 7>> m(
|
||||
std::extents<unsigned, D, 5, 7>(20), std::array<unsigned, 3>{4, 1, 200});
|
||||
}()),
|
||||
"layout_stride::mapping ctor: the provided extents and strides lead to a non-unique mapping");
|
||||
}
|
||||
// equal strides
|
||||
{
|
||||
// should work because one of the equal strides is associated with an extent of 1
|
||||
[[maybe_unused]] std::layout_stride::template mapping<std::extents<unsigned, D, 5, 1>> m1(
|
||||
std::extents<unsigned, D, 5, 1>(2), std::array<unsigned, 3>{5, 1, 5});
|
||||
[[maybe_unused]] std::layout_stride::template mapping<std::extents<unsigned, D, 5, 2>> m2(
|
||||
std::extents<unsigned, D, 5, 2>(1), std::array<unsigned, 3>{5, 1, 5});
|
||||
|
||||
// will fail because neither of the equal strides is associated with an extent of 1
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::layout_stride::template mapping<std::extents<unsigned, D, 5, 2>> m3(
|
||||
std::extents<unsigned, D, 5, 2>(2), std::array<unsigned, 3>{5, 1, 5});
|
||||
}()),
|
||||
"layout_stride::mapping ctor: the provided extents and strides lead to a non-unique mapping");
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// UNSUPPORTED: libcpp-hardening-mode=unchecked
|
||||
// XFAIL: availability-verbose_abort-missing
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class OtherIndexType>
|
||||
// constexpr mapping(const extents_type& e, const array<OtherIndexType, rank_>& s) noexcept;
|
||||
//
|
||||
// Constraints:
|
||||
// - is_convertible_v<const OtherIndexType&, index_type> is true, and
|
||||
// - is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// - s[i] > 0 is true for all i in the range [0, rank_).
|
||||
// - REQUIRED-SPAN-SIZE(e, s) is representable as a value of type index_type ([basic.fundamental]).
|
||||
// - If rank_ is greater than 0, then there exists a permutation P of the integers in the range [0, rank_),
|
||||
// such that s[pi] >= s[pi_1] * e.extent(pi_1) is true for all i in the range [1, rank_), where
|
||||
// pi is the ith element of P.
|
||||
// [Note 1: For layout_stride, this condition is necessary and sufficient for is_unique() to be true. end note]
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with e, and for all d in the range [0, rank_), direct-non-list-initializes strides_[d] with as_const(s[d]).
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
// the extents are representable but the product with strides is not, so we can't use it for layout_stride
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::layout_stride::template mapping<std::extents<char, D, 5>> m(
|
||||
std::extents<char, D, 5>(20), std::array<int, 2>{20, 1});
|
||||
}()),
|
||||
"layout_stride::mapping ctor: required span size is not representable as index_type.");
|
||||
|
||||
// check that if we first overflow in strides conversion we also fail
|
||||
static_assert(static_cast<unsigned char>(257u) == 1);
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::layout_stride::template mapping<std::extents<unsigned char, D, 5>> m(
|
||||
std::extents<unsigned char, D, 5>(20), std::array<unsigned, 2>{257, 1});
|
||||
}()),
|
||||
"layout_stride::mapping ctor: required span size is not representable as index_type.");
|
||||
|
||||
// negative strides are not allowed, check with unsigned index_type so we make sure we catch that
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::layout_stride::template mapping<std::extents<unsigned, D, 5>> m(
|
||||
std::extents<unsigned, D, 5>(20), std::array<int, 2>{20, -1});
|
||||
}()),
|
||||
"layout_stride::mapping ctor: all strides must be greater than 0");
|
||||
// zero strides are not allowed, check with unsigned index_type so we make sure we catch that
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::layout_stride::template mapping<std::extents<unsigned, D, 5>> m(
|
||||
std::extents<unsigned, D, 5>(20), std::array<unsigned, 2>{20, 0});
|
||||
}()),
|
||||
"layout_stride::mapping ctor: all strides must be greater than 0");
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// UNSUPPORTED: !libcpp-hardening-mode=debug
|
||||
// XFAIL: availability-verbose_abort-missing
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class OtherIndexType>
|
||||
// constexpr mapping(const extents_type& e, span<OtherIndexType, rank_> s) noexcept;
|
||||
//
|
||||
// Constraints:
|
||||
// - is_convertible_v<const OtherIndexType&, index_type> is true, and
|
||||
// - is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// - s[i] > 0 is true for all i in the range [0, rank_).
|
||||
// - REQUIRED-SPAN-SIZE(e, s) is representable as a value of type index_type ([basic.fundamental]).
|
||||
// - If rank_ is greater than 0, then there exists a permutation P of the integers in the range [0, rank_),
|
||||
// such that s[pi] >= s[pi_1] * e.extent(pi_1) is true for all i in the range [1, rank_), where
|
||||
// pi is the ith element of P.
|
||||
// [Note 1: For layout_stride, this condition is necessary and sufficient for is_unique() to be true. end note]
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with e, and for all d in the range [0, rank_), direct-non-list-initializes strides_[d] with as_const(s[d]).
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
// overlapping strides
|
||||
{
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::array<unsigned, 3> strides{4, 1, 200};
|
||||
std::layout_stride::template mapping<std::extents<unsigned, D, 5, 7>> m(
|
||||
std::extents<unsigned, D, 5, 7>(20), std::span(strides));
|
||||
}()),
|
||||
"layout_stride::mapping ctor: the provided extents and strides lead to a non-unique mapping");
|
||||
}
|
||||
|
||||
// equal strides
|
||||
{
|
||||
// should work because one of the equal strides is associated with an extent of 1
|
||||
std::array<unsigned, 3> strides{5, 1, 5};
|
||||
[[maybe_unused]] std::layout_stride::template mapping<std::extents<unsigned, D, 5, 1>> m1(
|
||||
std::extents<unsigned, D, 5, 1>(2), std::span(strides));
|
||||
[[maybe_unused]] std::layout_stride::template mapping<std::extents<unsigned, D, 5, 2>> m2(
|
||||
std::extents<unsigned, D, 5, 2>(1), std::span(strides));
|
||||
|
||||
// will fail because neither of the equal strides is associated with an extent of 1
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::layout_stride::template mapping<std::extents<unsigned, D, 5, 2>> m3(
|
||||
std::extents<unsigned, D, 5, 2>(2), std::span(strides));
|
||||
}()),
|
||||
"layout_stride::mapping ctor: the provided extents and strides lead to a non-unique mapping");
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// UNSUPPORTED: libcpp-hardening-mode=unchecked
|
||||
// XFAIL: availability-verbose_abort-missing
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class OtherIndexType>
|
||||
// constexpr mapping(const extents_type& e, span<OtherIndexType, rank_> s) noexcept;
|
||||
//
|
||||
// Constraints:
|
||||
// - is_convertible_v<const OtherIndexType&, index_type> is true, and
|
||||
// - is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// - s[i] > 0 is true for all i in the range [0, rank_).
|
||||
// - REQUIRED-SPAN-SIZE(e, s) is representable as a value of type index_type ([basic.fundamental]).
|
||||
// - If rank_ is greater than 0, then there exists a permutation P of the integers in the range [0, rank_),
|
||||
// such that s[pi] >= s[pi_1] * e.extent(pi_1) is true for all i in the range [1, rank_), where
|
||||
// pi is the ith element of P.
|
||||
// [Note 1: For layout_stride, this condition is necessary and sufficient for is_unique() to be true. end note]
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with e, and for all d in the range [0, rank_), direct-non-list-initializes strides_[d] with as_const(s[d]).
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
// value out of range
|
||||
{
|
||||
// the extents are representable but the product with strides is not, so we can't use it for layout_stride
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::array<int, 2> strides{20, 1};
|
||||
std::layout_stride::template mapping<std::extents<char, D, 5>> m(
|
||||
std::extents<char, D, 5>(20), std::span(strides));
|
||||
}()),
|
||||
"layout_stride::mapping ctor: required span size is not representable as index_type.");
|
||||
|
||||
// check that if we first overflow in strides conversion we also fail
|
||||
static_assert(static_cast<unsigned char>(257u) == 1);
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::array<unsigned, 2> strides{257, 1};
|
||||
std::layout_stride::template mapping<std::extents<unsigned char, D, 5>> m(
|
||||
std::extents<unsigned char, D, 5>(20), std::span(strides));
|
||||
}()),
|
||||
"layout_stride::mapping ctor: required span size is not representable as index_type.");
|
||||
|
||||
// negative strides are not allowed, check with unsigned index_type so we make sure we catch that
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::array<int, 2> strides{20, -1};
|
||||
std::layout_stride::template mapping<std::extents<unsigned, D, 5>> m(
|
||||
std::extents<unsigned, D, 5>(20), std::span(strides));
|
||||
}()),
|
||||
"layout_stride::mapping ctor: all strides must be greater than 0");
|
||||
// zero strides are not allowed, check with unsigned index_type so we make sure we catch that
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
([=] {
|
||||
std::array<unsigned, 2> strides{20, 0};
|
||||
std::layout_stride::template mapping<std::extents<unsigned, D, 5>> m(
|
||||
std::extents<unsigned, D, 5>(20), std::span(strides));
|
||||
}()),
|
||||
"layout_stride::mapping ctor: all strides must be greater than 0");
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// UNSUPPORTED: !libcpp-hardening-mode=debug
|
||||
// XFAIL: availability-verbose_abort-missing
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class... Indices>
|
||||
// constexpr index_type operator()(Indices... i) const noexcept;
|
||||
//
|
||||
// Constraints:
|
||||
// - sizeof...(Indices) == extents_type::rank() is true,
|
||||
// - (is_convertible_v<Indices, index_type> && ...) is true, and
|
||||
// - (is_nothrow_constructible_v<index_type, Indices> && ...) is true.
|
||||
//
|
||||
// Preconditions: extents_type::index-cast(i) is a multidimensional index in extents_ ([mdspan.overview]).
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
// value out of range
|
||||
{
|
||||
std::layout_stride::template mapping<std::extents<unsigned char, 5>> m;
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(-1), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(-130), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(5), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(1000), "layout_stride::mapping: out of bounds indexing");
|
||||
}
|
||||
{
|
||||
std::layout_stride::template mapping<std::extents<signed char, 5>> m;
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(-1), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(-130), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(5), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(1000), "layout_stride::mapping: out of bounds indexing");
|
||||
}
|
||||
{
|
||||
std::layout_stride::template mapping<std::dextents<unsigned char, 1>> m(
|
||||
std::dextents<unsigned char, 1>(5), std::array<int, 1>{1});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(-1), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(-130), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(5), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(1000), "layout_stride::mapping: out of bounds indexing");
|
||||
}
|
||||
{
|
||||
std::layout_stride::template mapping<std::dextents<signed char, 1>> m(
|
||||
std::dextents<signed char, 1>(5), std::array<int, 1>{1});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(-1), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(-130), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(5), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(1000), "layout_stride::mapping: out of bounds indexing");
|
||||
}
|
||||
{
|
||||
std::layout_stride::template mapping<std::dextents<int, 3>> m(
|
||||
std::dextents<int, 3>(5, 7, 9), std::array<int, 3>{1, 10, 100});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(-1, -1, -1), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(-1, 0, 0), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(0, -1, 0), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(0, 0, -1), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(5, 3, 3), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(3, 7, 3), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(3, 3, 9), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(5, 7, 9), "layout_stride::mapping: out of bounds indexing");
|
||||
}
|
||||
{
|
||||
std::layout_stride::template mapping<std::dextents<unsigned, 3>> m(
|
||||
std::dextents<int, 3>(5, 7, 9), std::array<int, 3>{1, 10, 100});
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(-1, -1, -1), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(-1, 0, 0), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(0, -1, 0), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(0, 0, -1), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(5, 3, 3), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(3, 7, 3), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(3, 3, 9), "layout_stride::mapping: out of bounds indexing");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m(5, 7, 9), "layout_stride::mapping: out of bounds indexing");
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// UNSUPPORTED: libcpp-hardening-mode=unchecked
|
||||
// XFAIL: availability-verbose_abort-missing
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// constexpr index_type stride(rank_type i) const noexcept { return strides_[i]; }
|
||||
|
||||
// We intercept this inside layout_stride to give a consistent error message with
|
||||
// layout_left and layout_right, technically the precondition is coming from the
|
||||
// array access.
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
// value out of range
|
||||
{
|
||||
std::layout_stride::template mapping<std::dextents<int, 3>> m(
|
||||
std::dextents<int, 3>(100, 100, 100), std::array<int, 3>{1, 100, 10000});
|
||||
|
||||
TEST_LIBCPP_ASSERT_FAILURE(m.stride(4), "invalid rank index");
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -42,7 +42,7 @@
|
||||
#include <mdspan>
|
||||
|
||||
#include "check_assertion.h"
|
||||
#include "../../../../../std/containers/views/mdspan/mdspan/CustomTestLayouts.h"
|
||||
#include "../../../../../std/containers/views/mdspan/CustomTestLayouts.h"
|
||||
|
||||
// We use a funky mapping in this test that doesn't check the dynamic/static extents mismatch itself
|
||||
int main(int, char**) {
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <mdspan>
|
||||
|
||||
#include "check_assertion.h"
|
||||
#include "../../../../../std/containers/views/mdspan/mdspan/CustomTestLayouts.h"
|
||||
#include "../../../../../std/containers/views/mdspan/CustomTestLayouts.h"
|
||||
|
||||
// We use a funky mapping in this test where required_span_size is much smaller than the size of the index space
|
||||
int main(int, char**) {
|
||||
|
@ -526,6 +526,7 @@ mdspan concepts
|
||||
mdspan cstddef
|
||||
mdspan limits
|
||||
mdspan span
|
||||
mdspan version
|
||||
memory atomic
|
||||
memory compare
|
||||
memory concepts
|
||||
|
|
@ -530,6 +530,7 @@ mdspan concepts
|
||||
mdspan cstddef
|
||||
mdspan limits
|
||||
mdspan span
|
||||
mdspan version
|
||||
memory atomic
|
||||
memory compare
|
||||
memory concepts
|
||||
|
|
@ -532,6 +532,7 @@ mdspan concepts
|
||||
mdspan cstddef
|
||||
mdspan limits
|
||||
mdspan span
|
||||
mdspan version
|
||||
memory atomic
|
||||
memory compare
|
||||
memory concepts
|
||||
|
|
@ -532,6 +532,7 @@ mdspan concepts
|
||||
mdspan cstddef
|
||||
mdspan limits
|
||||
mdspan span
|
||||
mdspan version
|
||||
memory atomic
|
||||
memory compare
|
||||
memory concepts
|
||||
|
|
@ -537,6 +537,7 @@ mdspan concepts
|
||||
mdspan cstddef
|
||||
mdspan limits
|
||||
mdspan span
|
||||
mdspan version
|
||||
memory atomic
|
||||
memory compare
|
||||
memory concepts
|
||||
|
|
@ -386,6 +386,7 @@ mdspan concepts
|
||||
mdspan cstddef
|
||||
mdspan limits
|
||||
mdspan span
|
||||
mdspan version
|
||||
memory compare
|
||||
memory cstddef
|
||||
memory cstdint
|
||||
|
|
@ -386,6 +386,7 @@ mdspan concepts
|
||||
mdspan cstddef
|
||||
mdspan limits
|
||||
mdspan span
|
||||
mdspan version
|
||||
memory compare
|
||||
memory cstddef
|
||||
memory cstdint
|
||||
|
|
@ -14,8 +14,8 @@
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#ifndef TEST_STD_CONTAINERS_VIEWS_MDSPAN_MDSPAN_CUSTOM_TEST_LAYOUTS_H
|
||||
#define TEST_STD_CONTAINERS_VIEWS_MDSPAN_MDSPAN_CUSTOM_TEST_LAYOUTS_H
|
||||
#ifndef TEST_STD_CONTAINERS_VIEWS_MDSPAN_CUSTOM_TEST_LAYOUTS_H
|
||||
#define TEST_STD_CONTAINERS_VIEWS_MDSPAN_CUSTOM_TEST_LAYOUTS_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@ -205,9 +205,9 @@ constexpr auto construct_mapping(layout_wrapping_integral<Wraps>, Extents exts)
|
||||
return typename layout_wrapping_integral<Wraps>::template mapping<Extents>(exts, not_extents_constructible_tag{});
|
||||
}
|
||||
|
||||
|
||||
// This layout does not check convertibility of extents for its conversion ctor
|
||||
// Allows triggering mdspan's ctor static assertion on convertibility of extents
|
||||
// It also allows for negative strides and offsets via runtime arguments
|
||||
class always_convertible_layout {
|
||||
public:
|
||||
template <class Extents>
|
||||
@ -239,8 +239,10 @@ private:
|
||||
|
||||
public:
|
||||
constexpr mapping() noexcept = delete;
|
||||
constexpr mapping(const mapping& other) noexcept : extents_(other.extents()){};
|
||||
constexpr mapping(const extents_type& ext) noexcept : extents_(ext){};
|
||||
constexpr mapping(const mapping& other) noexcept
|
||||
: extents_(other.extents_), offset_(other.offset_), scaling_(other.scaling_){};
|
||||
constexpr mapping(const extents_type& ext, index_type offset = 0, index_type scaling = 1) noexcept
|
||||
: extents_(ext), offset_(offset), scaling_(scaling){};
|
||||
|
||||
template <class OtherExtents>
|
||||
constexpr mapping(const mapping<OtherExtents>& other) noexcept {
|
||||
@ -256,10 +258,14 @@ public:
|
||||
} else {
|
||||
extents_ = extents_type();
|
||||
}
|
||||
offset_ = other.offset_;
|
||||
scaling_ = other.scaling_;
|
||||
}
|
||||
|
||||
constexpr mapping& operator=(const mapping& other) noexcept {
|
||||
extents_ = other.extents_;
|
||||
offset_ = other.offset_;
|
||||
scaling_ = other.scaling_;
|
||||
return *this;
|
||||
};
|
||||
|
||||
@ -269,7 +275,7 @@ public:
|
||||
index_type size = 1;
|
||||
for (size_t r = 0; r < extents_type::rank(); r++)
|
||||
size *= extents_.extent(r);
|
||||
return size;
|
||||
return std::max(size * scaling_ + offset_, offset_);
|
||||
}
|
||||
|
||||
template <std::integral... Indices>
|
||||
@ -277,16 +283,18 @@ public:
|
||||
(std::is_nothrow_constructible_v<index_type, Indices> && ...))
|
||||
constexpr index_type operator()(Indices... idx) const noexcept {
|
||||
std::array<index_type, extents_type::rank()> idx_a{static_cast<index_type>(static_cast<index_type>(idx))...};
|
||||
return [&]<size_t... Pos>(std::index_sequence<Pos...>) {
|
||||
index_type res = 0;
|
||||
((res = idx_a[extents_type::rank() - 1 - Pos] + extents_.extent(extents_type::rank() - 1 - Pos) * res), ...);
|
||||
return res;
|
||||
}(std::make_index_sequence<sizeof...(Indices)>());
|
||||
return offset_ +
|
||||
scaling_ * ([&]<size_t... Pos>(std::index_sequence<Pos...>) {
|
||||
index_type res = 0;
|
||||
((res = idx_a[extents_type::rank() - 1 - Pos] + extents_.extent(extents_type::rank() - 1 - Pos) * res),
|
||||
...);
|
||||
return res;
|
||||
}(std::make_index_sequence<sizeof...(Indices)>()));
|
||||
}
|
||||
|
||||
static constexpr bool is_always_unique() noexcept { return false; }
|
||||
static constexpr bool is_always_unique() noexcept { return true; }
|
||||
static constexpr bool is_always_exhaustive() noexcept { return true; }
|
||||
static constexpr bool is_always_strided() noexcept { return false; }
|
||||
static constexpr bool is_always_strided() noexcept { return true; }
|
||||
|
||||
static constexpr bool is_unique() noexcept { return true; }
|
||||
static constexpr bool is_exhaustive() noexcept { return true; }
|
||||
@ -296,15 +304,15 @@ public:
|
||||
requires(extents_type::rank() > 0)
|
||||
{
|
||||
index_type s = 1;
|
||||
for (rank_type i = extents_type::rank() - 1; i > r; i--)
|
||||
for (rank_type i = 0; i < r; i++)
|
||||
s *= extents_.extent(i);
|
||||
return s;
|
||||
return s * scaling_;
|
||||
}
|
||||
|
||||
template <class OtherExtents>
|
||||
requires(OtherExtents::rank() == extents_type::rank())
|
||||
friend constexpr bool operator==(const mapping& lhs, const mapping<OtherExtents>& rhs) noexcept {
|
||||
return lhs.extents() == rhs.extents();
|
||||
return lhs.extents() == rhs.extents() && lhs.offset_ == rhs.offset && lhs.scaling_ == rhs.scaling_;
|
||||
}
|
||||
|
||||
friend constexpr void swap(mapping& x, mapping& y) noexcept {
|
||||
@ -320,6 +328,11 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
template <class>
|
||||
friend class mapping;
|
||||
|
||||
extents_type extents_{};
|
||||
index_type offset_{};
|
||||
index_type scaling_{};
|
||||
};
|
||||
#endif // TEST_STD_CONTAINERS_VIEWS_MDSPAN_MDSPAN_CUSTOM_TEST_LAYOUTS_H
|
||||
#endif // TEST_STD_CONTAINERS_VIEWS_MDSPAN_CUSTOM_TEST_LAYOUTS_H
|
@ -0,0 +1,114 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class OtherExtents>
|
||||
// constexpr explicit(extents_type::rank() > 0)
|
||||
// mapping(const layout_stride::mapping<OtherExtents>& other);
|
||||
//
|
||||
// Constraints: is_constructible_v<extents_type, OtherExtents> is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// - If extents_type::rank() > 0 is true, then for all r in the range [0, extents_type::rank()),
|
||||
// other.stride(r) equals other.extents().fwd-prod-of-extents(r), and
|
||||
// - other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with other.extents().
|
||||
|
||||
#include <mdspan>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <bool implicit, class ToE, class FromE>
|
||||
constexpr void test_conversion(FromE src_exts) {
|
||||
using To = std::layout_left::mapping<ToE>;
|
||||
using From = std::layout_stride::mapping<FromE>;
|
||||
std::array<typename FromE::index_type, FromE::rank()> strides;
|
||||
if constexpr (FromE::rank() > 0) {
|
||||
strides[0] = 1;
|
||||
for (size_t r = 1; r < FromE::rank(); r++)
|
||||
strides[r] = src_exts.extent(r - 1) * strides[r - 1];
|
||||
}
|
||||
From src(src_exts, strides);
|
||||
|
||||
ASSERT_NOEXCEPT(To(src));
|
||||
To dest(src);
|
||||
assert(dest == src);
|
||||
|
||||
if constexpr (implicit) {
|
||||
To dest_implicit = src;
|
||||
assert(dest_implicit == src);
|
||||
} else {
|
||||
assert((!std::is_convertible_v<From, To>));
|
||||
}
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr void test_conversion() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
// clang-format off
|
||||
test_conversion<true, std::extents<T1>>(std::extents<T2>());
|
||||
test_conversion<false, std::extents<T1, D>>(std::extents<T2, D>(5));
|
||||
test_conversion<false, std::extents<T1, 5>>(std::extents<T2, D>(5));
|
||||
test_conversion<false, std::extents<T1, 5>>(std::extents<T2, 5>());
|
||||
test_conversion<false, std::extents<T1, 5, D>>(std::extents<T2, D, D>(5, 5));
|
||||
test_conversion<false, std::extents<T1, D, D>>(std::extents<T2, D, D>(5, 5));
|
||||
test_conversion<false, std::extents<T1, D, D>>(std::extents<T2, D, 7>(5));
|
||||
test_conversion<false, std::extents<T1, 5, 7>>(std::extents<T2, 5, 7>());
|
||||
test_conversion<false, std::extents<T1, 5, D, 8, D, D>>(std::extents<T2, D, D, 8, 9, 1>(5, 7));
|
||||
test_conversion<false, std::extents<T1, D, D, D, D, D>>(
|
||||
std::extents<T2, D, D, D, D, D>(5, 7, 8, 9, 1));
|
||||
test_conversion<false, std::extents<T1, D, D, 8, 9, D>>(std::extents<T2, D, 7, 8, 9, 1>(5));
|
||||
test_conversion<false, std::extents<T1, 5, 7, 8, 9, 1>>(std::extents<T2, 5, 7, 8, 9, 1>());
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
template <class IdxT, size_t... Extents>
|
||||
using ll_mapping_t = typename std::layout_left::template mapping<std::extents<IdxT, Extents...>>;
|
||||
template <class IdxT, size_t... Extents>
|
||||
using ls_mapping_t = typename std::layout_stride::template mapping<std::extents<IdxT, Extents...>>;
|
||||
|
||||
constexpr void test_rank_mismatch() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
static_assert(!std::is_constructible_v<ll_mapping_t<int, D>, ls_mapping_t<int>>);
|
||||
static_assert(!std::is_constructible_v<ll_mapping_t<int>, ls_mapping_t<int, D, D>>);
|
||||
static_assert(!std::is_constructible_v<ll_mapping_t<int, D>, ls_mapping_t<int, D, D>>);
|
||||
static_assert(!std::is_constructible_v<ll_mapping_t<int, D, D, D>, ls_mapping_t<int, D, D>>);
|
||||
}
|
||||
|
||||
constexpr void test_static_extent_mismatch() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
static_assert(!std::is_constructible_v<ll_mapping_t<int, D, 5>, ls_mapping_t<int, D, 4>>);
|
||||
static_assert(!std::is_constructible_v<ll_mapping_t<int, 5>, ls_mapping_t<int, 4>>);
|
||||
static_assert(!std::is_constructible_v<ll_mapping_t<int, 5, D>, ls_mapping_t<int, 4, D>>);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test_conversion<int, int>();
|
||||
test_conversion<int, size_t>();
|
||||
test_conversion<size_t, int>();
|
||||
test_conversion<size_t, long>();
|
||||
test_rank_mismatch();
|
||||
test_static_extent_mismatch();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class OtherExtents>
|
||||
// constexpr explicit(extents_type::rank() > 0)
|
||||
// mapping(const layout_stride::mapping<OtherExtents>& other);
|
||||
//
|
||||
// Constraints: is_constructible_v<extents_type, OtherExtents> is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// - If extents_type::rank() > 0 is true, then for all r in the range [0, extents_type::rank()),
|
||||
// other.stride(r) equals other.extents().fwd-prod-of-extents(r), and
|
||||
// - other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with other.extents().
|
||||
|
||||
#include <mdspan>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <bool implicit, class ToE, class FromE>
|
||||
constexpr void test_conversion(FromE src_exts) {
|
||||
using To = std::layout_left::mapping<ToE>;
|
||||
using From = std::layout_stride::mapping<FromE>;
|
||||
std::array<typename FromE::index_type, FromE::rank()> strides;
|
||||
if constexpr (FromE::rank() > 0) {
|
||||
strides[0] = 1;
|
||||
for (size_t r = 1; r < FromE::rank(); r++)
|
||||
strides[r] = src_exts.extent(r - 1) * strides[r - 1];
|
||||
}
|
||||
From src(src_exts, strides);
|
||||
|
||||
ASSERT_NOEXCEPT(To(src));
|
||||
To dest(src);
|
||||
assert(dest == src);
|
||||
|
||||
if constexpr (implicit) {
|
||||
To dest_implicit = src;
|
||||
assert(dest_implicit == src);
|
||||
} else {
|
||||
assert((!std::is_convertible_v<From, To>));
|
||||
}
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr void test_conversion() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
// clang-format off
|
||||
test_conversion<true, std::extents<T1>>(std::extents<T2>());
|
||||
test_conversion<false, std::extents<T1, D>>(std::extents<T2, D>(5));
|
||||
test_conversion<false, std::extents<T1, 5>>(std::extents<T2, D>(5));
|
||||
test_conversion<false, std::extents<T1, 5>>(std::extents<T2, 5>());
|
||||
test_conversion<false, std::extents<T1, 5, D>>(std::extents<T2, D, D>(5, 5));
|
||||
test_conversion<false, std::extents<T1, D, D>>(std::extents<T2, D, D>(5, 5));
|
||||
test_conversion<false, std::extents<T1, D, D>>(std::extents<T2, D, 7>(5));
|
||||
test_conversion<false, std::extents<T1, 5, 7>>(std::extents<T2, 5, 7>());
|
||||
test_conversion<false, std::extents<T1, 5, D, 8, D, D>>(std::extents<T2, D, D, 8, 9, 1>(5, 7));
|
||||
test_conversion<false, std::extents<T1, D, D, D, D, D>>(
|
||||
std::extents<T2, D, D, D, D, D>(5, 7, 8, 9, 1));
|
||||
test_conversion<false, std::extents<T1, D, D, 8, 9, D>>(std::extents<T2, D, 7, 8, 9, 1>(5));
|
||||
test_conversion<false, std::extents<T1, 5, 7, 8, 9, 1>>(std::extents<T2, 5, 7, 8, 9, 1>());
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
template <class IdxT, size_t... Extents>
|
||||
using lr_mapping_t = typename std::layout_right::template mapping<std::extents<IdxT, Extents...>>;
|
||||
template <class IdxT, size_t... Extents>
|
||||
using ls_mapping_t = typename std::layout_stride::template mapping<std::extents<IdxT, Extents...>>;
|
||||
|
||||
constexpr void test_rank_mismatch() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
static_assert(!std::is_constructible_v<lr_mapping_t<int, D>, ls_mapping_t<int>>);
|
||||
static_assert(!std::is_constructible_v<lr_mapping_t<int>, ls_mapping_t<int, D, D>>);
|
||||
static_assert(!std::is_constructible_v<lr_mapping_t<int, D>, ls_mapping_t<int, D, D>>);
|
||||
static_assert(!std::is_constructible_v<lr_mapping_t<int, D, D, D>, ls_mapping_t<int, D, D>>);
|
||||
}
|
||||
|
||||
constexpr void test_static_extent_mismatch() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
static_assert(!std::is_constructible_v<lr_mapping_t<int, D, 5>, ls_mapping_t<int, D, 4>>);
|
||||
static_assert(!std::is_constructible_v<lr_mapping_t<int, 5>, ls_mapping_t<int, 4>>);
|
||||
static_assert(!std::is_constructible_v<lr_mapping_t<int, 5, D>, ls_mapping_t<int, 4, D>>);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test_conversion<int, int>();
|
||||
test_conversion<int, size_t>();
|
||||
test_conversion<size_t, int>();
|
||||
test_conversion<size_t, long>();
|
||||
test_rank_mismatch();
|
||||
test_static_extent_mismatch();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,198 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class OtherMapping>
|
||||
// friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept;
|
||||
//
|
||||
// Constraints:
|
||||
// - layout-mapping-alike<OtherMapping> is satisfied.
|
||||
// - rank_ == OtherMapping::extents_type::rank() is true.
|
||||
// - OtherMapping::is_always_strided() is true.
|
||||
//
|
||||
// Preconditions: OtherMapping meets the layout mapping requirements ([mdspan.layout.policy.reqmts]).
|
||||
//
|
||||
// Returns: true if x.extents() == y.extents() is true, OFFSET(y) == 0 is true, and each of x.stride(r) == y.stride(r) is true for r in the range [0, x.extents().rank()). Otherwise, false.
|
||||
|
||||
#include <mdspan>
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../CustomTestLayouts.h"
|
||||
|
||||
template <class E1, class E2>
|
||||
concept layout_mapping_comparable = requires(
|
||||
E1 e1,
|
||||
E2 e2,
|
||||
std::array<typename E1::index_type, E1::rank()> s1,
|
||||
std::array<typename E1::index_type, E1::rank()> s2) {
|
||||
std::layout_stride::mapping<E1>(e1, s1) == std::layout_stride::mapping<E2>(e2, s2);
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr void test_comparison_different_rank() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
// sanity check same rank
|
||||
static_assert(layout_mapping_comparable<std::extents<T1, D>, std::extents<T2, D>>);
|
||||
static_assert(layout_mapping_comparable<std::extents<T1, 5>, std::extents<T2, D>>);
|
||||
static_assert(layout_mapping_comparable<std::extents<T1, D>, std::extents<T2, 5>>);
|
||||
static_assert(layout_mapping_comparable<std::extents<T1, 5>, std::extents<T2, 5>>);
|
||||
|
||||
// not equality comparable when rank is not the same
|
||||
static_assert(!layout_mapping_comparable<std::extents<T1>, std::extents<T2, D>>);
|
||||
static_assert(!layout_mapping_comparable<std::extents<T1>, std::extents<T2, 1>>);
|
||||
static_assert(!layout_mapping_comparable<std::extents<T1, D>, std::extents<T2>>);
|
||||
static_assert(!layout_mapping_comparable<std::extents<T1, 1>, std::extents<T2>>);
|
||||
static_assert(!layout_mapping_comparable<std::extents<T1, D>, std::extents<T2, D, D>>);
|
||||
static_assert(!layout_mapping_comparable<std::extents<T1, 5>, std::extents<T2, 5, D>>);
|
||||
static_assert(!layout_mapping_comparable<std::extents<T1, 5>, std::extents<T2, 5, 1>>);
|
||||
static_assert(!layout_mapping_comparable<std::extents<T1, D, D>, std::extents<T2, D>>);
|
||||
static_assert(!layout_mapping_comparable<std::extents<T1, 5, D>, std::extents<T2, 5>>);
|
||||
static_assert(!layout_mapping_comparable<std::extents<T1, 5, 1>, std::extents<T2, 5>>);
|
||||
}
|
||||
|
||||
template <class To, class From>
|
||||
constexpr void test_comparison(
|
||||
bool equal,
|
||||
To dest_exts,
|
||||
From src_exts,
|
||||
std::array<int, To::rank()> dest_strides,
|
||||
std::array<int, From::rank()> src_strides) {
|
||||
std::layout_stride::mapping<To> dest(dest_exts, dest_strides);
|
||||
std::layout_stride::mapping<From> src(src_exts, src_strides);
|
||||
ASSERT_NOEXCEPT(dest == src);
|
||||
assert((dest == src) == equal);
|
||||
assert((dest != src) == !equal);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr void test_comparison_same_rank() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
test_comparison(true, std::extents<T1>(), std::extents<T2>(), std::array<int, 0>{}, std::array<int, 0>{});
|
||||
|
||||
test_comparison(true, std::extents<T1, D>(5), std::extents<T2, D>(5), std::array<int, 1>{1}, std::array<int, 1>{1});
|
||||
test_comparison(true, std::extents<T1, D>(0), std::extents<T2, D>(0), std::array<int, 1>{1}, std::array<int, 1>{1});
|
||||
test_comparison(true, std::extents<T1, 5>(), std::extents<T2, D>(5), std::array<int, 1>{3}, std::array<int, 1>{3});
|
||||
test_comparison(true, std::extents<T1, D>(5), std::extents<T2, 5>(), std::array<int, 1>{1}, std::array<int, 1>{1});
|
||||
test_comparison(true, std::extents<T1, 5>(), std::extents< T2, 5>(), std::array<int, 1>{1}, std::array<int, 1>{1});
|
||||
test_comparison(false, std::extents<T1, 5>(), std::extents<T2, D>(5), std::array<int, 1>{2}, std::array<int, 1>{1});
|
||||
test_comparison(false, std::extents<T1, D>(5), std::extents<T2, D>(5), std::array<int, 1>{2}, std::array<int, 1>{1});
|
||||
test_comparison(false, std::extents<T1, D>(5), std::extents<T2, D>(7), std::array<int, 1>{1}, std::array<int, 1>{1});
|
||||
test_comparison(false, std::extents<T1, 5>(), std::extents<T2, D>(7), std::array<int, 1>{1}, std::array<int, 1>{1});
|
||||
test_comparison(false, std::extents<T1, D>(5), std::extents<T2, 7>(), std::array<int, 1>{1}, std::array<int, 1>{1});
|
||||
test_comparison(false, std::extents<T1, 5>(), std::extents<T2, 7>(), std::array<int, 1>{1}, std::array<int, 1>{1});
|
||||
|
||||
test_comparison(
|
||||
true,
|
||||
std::extents<T1, D, D, D, D, D>(5, 6, 7, 8, 9),
|
||||
std::extents<T2, D, D, D, D, D>(5, 6, 7, 8, 9),
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000},
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000});
|
||||
test_comparison(
|
||||
true,
|
||||
std::extents<T1, D, 6, D, 8, D>(5, 7, 9),
|
||||
std::extents<T2, 5, D, D, 8, 9>(6, 7),
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000},
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000});
|
||||
test_comparison(
|
||||
true,
|
||||
std::extents<T1, 5, 6, 7, 8, 9>(5, 6, 7, 8, 9),
|
||||
std::extents<T2, 5, 6, 7, 8, 9>(),
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000},
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000});
|
||||
test_comparison(
|
||||
false,
|
||||
std::extents<T1, 5, 6, 7, 8, 9>(5, 6, 7, 8, 9),
|
||||
std::extents<T2, 5, 6, 7, 8, 9>(),
|
||||
std::array<int, 5>{2, 20, 200, 20000, 2000},
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000});
|
||||
test_comparison(
|
||||
false,
|
||||
std::extents<T1, D, D, D, D, D>(5, 6, 7, 8, 9),
|
||||
std::extents<T2, D, D, D, D, D>(5, 6, 3, 8, 9),
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000},
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000});
|
||||
test_comparison(
|
||||
false,
|
||||
std::extents<T1, D, 6, D, 8, D>(5, 7, 9),
|
||||
std::extents<T2, 5, D, D, 3, 9>(6, 7),
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000},
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000});
|
||||
test_comparison(
|
||||
false,
|
||||
std::extents<T1, 5, 6, 7, 8, 9>(5, 6, 7, 8, 9),
|
||||
std::extents<T2, 5, 6, 7, 3, 9>(),
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000},
|
||||
std::array<int, 5>{2, 20, 200, 2000, 20000});
|
||||
}
|
||||
|
||||
template <class OtherLayout, class E1, class E2, class... OtherArgs>
|
||||
constexpr void test_comparison_with(
|
||||
bool expect_equal, E1 e1, std::array<typename E1::index_type, E1::rank()> strides, E2 e2, OtherArgs... other_args) {
|
||||
typename std::layout_stride::template mapping<E1> map(e1, strides);
|
||||
typename OtherLayout::template mapping<E2> other_map(e2, other_args...);
|
||||
|
||||
assert((map == other_map) == expect_equal);
|
||||
}
|
||||
|
||||
template <class OtherLayout>
|
||||
constexpr void test_comparison_with() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
bool is_left_based =
|
||||
std::is_same_v<OtherLayout, std::layout_left> || std::is_same_v<OtherLayout, always_convertible_layout>;
|
||||
test_comparison_with<OtherLayout>(true, std::extents<int>(), std::array<int, 0>{}, std::extents<unsigned>());
|
||||
test_comparison_with<OtherLayout>(true, std::extents<int, 5>(), std::array<int, 1>{1}, std::extents<unsigned, 5>());
|
||||
test_comparison_with<OtherLayout>(true, std::extents<int, D>(5), std::array<int, 1>{1}, std::extents<unsigned, 5>());
|
||||
test_comparison_with<OtherLayout>(false, std::extents<int, D>(5), std::array<int, 1>{2}, std::extents<unsigned, 5>());
|
||||
test_comparison_with<OtherLayout>(
|
||||
is_left_based, std::extents<int, D, D>(5, 7), std::array<int, 2>{1, 5}, std::extents<unsigned, D, D>(5, 7));
|
||||
test_comparison_with<OtherLayout>(
|
||||
!is_left_based, std::extents<int, D, D>(5, 7), std::array<int, 2>{7, 1}, std::extents<unsigned, D, D>(5, 7));
|
||||
test_comparison_with<OtherLayout>(
|
||||
false, std::extents<int, D, D>(5, 7), std::array<int, 2>{8, 1}, std::extents<unsigned, D, D>(5, 7));
|
||||
|
||||
if constexpr (std::is_same_v<OtherLayout, always_convertible_layout>) {
|
||||
// test layout with strides not equal to product of extents
|
||||
test_comparison_with<OtherLayout>(
|
||||
true, std::extents<int, D, D>(5, 7), std::array<int, 2>{2, 10}, std::extents<unsigned, D, D>(5, 7), 0, 2);
|
||||
// make sure that offset != 0 results in false
|
||||
test_comparison_with<OtherLayout>(
|
||||
false, std::extents<int, D, D>(5, 7), std::array<int, 2>{2, 10}, std::extents<unsigned, D, D>(5, 7), 1, 2);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr void test_comparison_index_type() {
|
||||
test_comparison_same_rank<T1, T2>();
|
||||
test_comparison_different_rank<T1, T2>();
|
||||
test_comparison_with<std::layout_right>();
|
||||
test_comparison_with<std::layout_left>();
|
||||
test_comparison_with<always_convertible_layout>();
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test_comparison_index_type<int, int>();
|
||||
test_comparison_index_type<int, size_t>();
|
||||
test_comparison_index_type<size_t, int>();
|
||||
test_comparison_index_type<size_t, long>();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// Test default construction:
|
||||
//
|
||||
// constexpr mapping() noexcept;
|
||||
//
|
||||
//
|
||||
// Preconditions: layout_right::mapping<extents_type>().required_span_size() is representable as a value of type index_type ([basic.fundamental]).
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with extents_type(), and for all d in the range [0, rank_),
|
||||
// direct-non-list-initializes strides_[d] with layout_right::mapping<extents_type>().stride(d).
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class E>
|
||||
constexpr void test_construction() {
|
||||
using M = std::layout_stride::mapping<E>;
|
||||
ASSERT_NOEXCEPT(M{});
|
||||
M m;
|
||||
E e;
|
||||
|
||||
// check correct extents are returned
|
||||
ASSERT_NOEXCEPT(m.extents());
|
||||
assert(m.extents() == e);
|
||||
|
||||
// check required_span_size()
|
||||
typename E::index_type expected_size = 1;
|
||||
for (typename E::rank_type r = 0; r < E::rank(); r++)
|
||||
expected_size *= e.extent(r);
|
||||
assert(m.required_span_size() == expected_size);
|
||||
|
||||
// check strides: node stride function is constrained on rank>0, e.extent(r) is not
|
||||
auto strides = m.strides();
|
||||
ASSERT_NOEXCEPT(m.strides());
|
||||
if constexpr (E::rank() > 0) {
|
||||
std::layout_right::mapping<E> m_right;
|
||||
for (typename E::rank_type r = 0; r < E::rank(); r++) {
|
||||
assert(m.stride(r) == m_right.stride(r));
|
||||
assert(strides[r] == m.stride(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
test_construction<std::extents<int>>();
|
||||
test_construction<std::extents<unsigned, D>>();
|
||||
test_construction<std::extents<unsigned, 7>>();
|
||||
test_construction<std::extents<unsigned, 0>>();
|
||||
test_construction<std::extents<unsigned, 7, 8>>();
|
||||
test_construction<std::extents<int64_t, D, 8, D, D>>();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class OtherIndexType>
|
||||
// constexpr mapping(const extents_type& e, array<OtherIndexType, rank_> s) noexcept;
|
||||
//
|
||||
// Constraints:
|
||||
// - is_convertible_v<const OtherIndexType&, index_type> is true, and
|
||||
// - is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// - s[i] > 0 is true for all i in the range [0, rank_).
|
||||
// - REQUIRED-SPAN-SIZE(e, s) is representable as a value of type index_type ([basic.fundamental]).
|
||||
// - If rank_ is greater than 0, then there exists a permutation P of the integers in the range [0, rank_),
|
||||
// such that s[pi] >= s[pi_1] * e.extent(pi_1) is true for all i in the range [1, rank_), where pi is the ith element of P.
|
||||
// Note 1: For layout_stride, this condition is necessary and sufficient for is_unique() to be true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with e, and for all d in the range [0, rank_),
|
||||
// direct-non-list-initializes strides_[d] with as_const(s[d]).
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../ConvertibleToIntegral.h"
|
||||
|
||||
template <class E, class S>
|
||||
constexpr void test_construction(E e, S s) {
|
||||
using M = std::layout_stride::mapping<E>;
|
||||
ASSERT_NOEXCEPT(M{e, s});
|
||||
M m(e, s);
|
||||
|
||||
// check correct extents are returned
|
||||
ASSERT_NOEXCEPT(m.extents());
|
||||
assert(m.extents() == e);
|
||||
|
||||
// check required_span_size()
|
||||
typename E::index_type expected_size = 1;
|
||||
for (typename E::rank_type r = 0; r < E::rank(); r++) {
|
||||
if (e.extent(r) == 0) {
|
||||
expected_size = 0;
|
||||
break;
|
||||
}
|
||||
expected_size += (e.extent(r) - 1) * static_cast<typename E::index_type>(s[r]);
|
||||
}
|
||||
assert(m.required_span_size() == expected_size);
|
||||
|
||||
// check strides: node stride function is constrained on rank>0, e.extent(r) is not
|
||||
auto strides = m.strides();
|
||||
ASSERT_NOEXCEPT(m.strides());
|
||||
if constexpr (E::rank() > 0) {
|
||||
for (typename E::rank_type r = 0; r < E::rank(); r++) {
|
||||
assert(m.stride(r) == static_cast<typename E::index_type>(s[r]));
|
||||
assert(strides[r] == m.stride(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
{
|
||||
std::array<int, 0> s{};
|
||||
test_construction(std::extents<int>(), s);
|
||||
}
|
||||
{
|
||||
std::array<int, 1> s{1};
|
||||
test_construction(std::extents<unsigned, D>(7), s);
|
||||
}
|
||||
{
|
||||
std::array<int, 1> s{1};
|
||||
test_construction(std::extents<unsigned, D>(0), s);
|
||||
}
|
||||
{
|
||||
std::array<int, 1> s{2};
|
||||
test_construction(std::extents<unsigned, 7>(), s);
|
||||
}
|
||||
{
|
||||
std::array<IntType, 1> s{1};
|
||||
test_construction(std::extents<int, D>(7), s);
|
||||
}
|
||||
{
|
||||
std::array<int, 2> s{3, 30};
|
||||
test_construction(std::extents<unsigned, 7, 8>(), s);
|
||||
}
|
||||
{
|
||||
std::array<int, 4> s{20, 2, 200, 2000};
|
||||
test_construction(std::extents<int64_t, D, 8, D, D>(7, 9, 10), s);
|
||||
test_construction(std::extents<int64_t, D, 8, D, D>(0, 9, 10), s);
|
||||
test_construction(std::extents<int64_t, D, 8, D, D>(0, 8, 0), s);
|
||||
}
|
||||
{
|
||||
std::array<int, 4> s{200, 20, 20, 2000};
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 0, 8, 9), s);
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 8, 0, 9), s);
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 8, 9), s);
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 8, 1, 9), s);
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 1, 9), s);
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 0, 0, 9), s);
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 1, 9), s);
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 0, 9), s);
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 0, 1, 9), s);
|
||||
}
|
||||
|
||||
{
|
||||
using mapping_t = std::layout_stride::mapping<std::dextents<unsigned, 2>>;
|
||||
// wrong strides size
|
||||
static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::array<int, 3>>);
|
||||
static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::array<int, 1>>);
|
||||
// wrong extents rank
|
||||
static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 3>, std::array<int, 2>>);
|
||||
// none-convertible strides
|
||||
static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::array<IntType, 2>>);
|
||||
}
|
||||
{
|
||||
// not no-throw constructible index_type from stride
|
||||
using mapping_t = std::layout_stride::mapping<std::dextents<unsigned char, 2>>;
|
||||
static_assert(std::is_convertible_v<IntType, unsigned char>);
|
||||
static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::array<IntType, 2>>);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class OtherIndexType>
|
||||
// constexpr mapping(const extents_type& e, span<OtherIndexType, rank_> s) noexcept;
|
||||
//
|
||||
// Constraints:
|
||||
// - is_convertible_v<const OtherIndexType&, index_type> is true, and
|
||||
// - is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// - s[i] > 0 is true for all i in the range [0, rank_).
|
||||
// - REQUIRED-SPAN-SIZE(e, s) is representable as a value of type index_type ([basic.fundamental]).
|
||||
// - If rank_ is greater than 0, then there exists a permutation P of the integers in the range [0, rank_),
|
||||
// such that s[pi] >= s[pi_1] * e.extent(pi_1) is true for all i in the range [1, rank_), where pi is the ith element of P.
|
||||
// Note 1: For layout_stride, this condition is necessary and sufficient for is_unique() to be true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with e, and for all d in the range [0, rank_),
|
||||
// direct-non-list-initializes strides_[d] with as_const(s[d]).
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../ConvertibleToIntegral.h"
|
||||
|
||||
template <class E, class S>
|
||||
constexpr void test_construction(E e, S s) {
|
||||
using M = std::layout_stride::mapping<E>;
|
||||
ASSERT_NOEXCEPT(M{e, s});
|
||||
M m(e, s);
|
||||
|
||||
// check correct extents are returned
|
||||
ASSERT_NOEXCEPT(m.extents());
|
||||
assert(m.extents() == e);
|
||||
|
||||
// check required_span_size()
|
||||
typename E::index_type expected_size = 1;
|
||||
for (typename E::rank_type r = 0; r < E::rank(); r++) {
|
||||
if (e.extent(r) == 0) {
|
||||
expected_size = 0;
|
||||
break;
|
||||
}
|
||||
expected_size += (e.extent(r) - 1) * static_cast<typename E::index_type>(s[r]);
|
||||
}
|
||||
assert(m.required_span_size() == expected_size);
|
||||
|
||||
// check strides: node stride function is constrained on rank>0, e.extent(r) is not
|
||||
auto strides = m.strides();
|
||||
ASSERT_NOEXCEPT(m.strides());
|
||||
if constexpr (E::rank() > 0) {
|
||||
for (typename E::rank_type r = 0; r < E::rank(); r++) {
|
||||
assert(m.stride(r) == static_cast<typename E::index_type>(s[r]));
|
||||
assert(strides[r] == m.stride(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
{
|
||||
std::array<int, 0> s{};
|
||||
test_construction(std::extents<int>(), std::span(s));
|
||||
}
|
||||
{
|
||||
std::array<int, 1> s{1};
|
||||
test_construction(std::extents<unsigned, D>(7), std::span(s));
|
||||
}
|
||||
{
|
||||
std::array<int, 1> s{1};
|
||||
test_construction(std::extents<unsigned, D>(0), std::span(s));
|
||||
}
|
||||
{
|
||||
std::array<int, 1> s{2};
|
||||
test_construction(std::extents<unsigned, 7>(), std::span(s));
|
||||
}
|
||||
{
|
||||
std::array<IntType, 1> s{1};
|
||||
test_construction(std::extents<int, D>(7), std::span(s));
|
||||
}
|
||||
{
|
||||
std::array<int, 2> s{3, 30};
|
||||
test_construction(std::extents<unsigned, 7, 8>(), std::span(s));
|
||||
}
|
||||
{
|
||||
std::array<int, 4> s{20, 2, 200, 2000};
|
||||
test_construction(std::extents<int64_t, D, 8, D, D>(7, 9, 10), std::span(s));
|
||||
}
|
||||
{
|
||||
std::array<int, 4> s{20, 2, 200, 2000};
|
||||
test_construction(std::extents<int64_t, D, 8, D, D>(7, 0, 10), std::span(s));
|
||||
test_construction(std::extents<int64_t, D, 8, D, D>(0, 9, 10), std::span(s));
|
||||
test_construction(std::extents<int64_t, D, 8, D, D>(0, 8, 0), std::span(s));
|
||||
}
|
||||
{
|
||||
std::array<int, 4> s{200, 20, 20, 2000};
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 0, 8, 9), std::span(s));
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 8, 0, 9), std::span(s));
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 8, 9), std::span(s));
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 8, 1, 9), std::span(s));
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 1, 9), std::span(s));
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 0, 0, 9), std::span(s));
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 1, 9), std::span(s));
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 1, 0, 9), std::span(s));
|
||||
test_construction(std::extents<int64_t, D, D, D, D>(7, 0, 1, 9), std::span(s));
|
||||
}
|
||||
|
||||
{
|
||||
using mapping_t = std::layout_stride::mapping<std::dextents<unsigned, 2>>;
|
||||
// wrong strides size
|
||||
static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::span<int, 3>>);
|
||||
static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::span<int, 1>>);
|
||||
// wrong extents rank
|
||||
static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 3>, std::span<int, 2>>);
|
||||
// none-convertible strides
|
||||
static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::span<IntType, 2>>);
|
||||
}
|
||||
{
|
||||
// not no-throw constructible index_type from stride
|
||||
using mapping_t = std::layout_stride::mapping<std::dextents<unsigned char, 2>>;
|
||||
static_assert(std::is_convertible_v<IntType, unsigned char>);
|
||||
static_assert(!std::is_constructible_v<mapping_t, std::dextents<int, 2>, std::span<IntType, 2>>);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class StridedLayoutMapping>
|
||||
// constexpr explicit(see below)
|
||||
// mapping(const StridedLayoutMapping& other) noexcept;
|
||||
//
|
||||
// Constraints:
|
||||
// - layout-mapping-alike<StridedLayoutMapping> is satisfied.
|
||||
// - is_constructible_v<extents_type, typename StridedLayoutMapping::extents_type> is true.
|
||||
// - StridedLayoutMapping::is_always_unique() is true.
|
||||
// - StridedLayoutMapping::is_always_strided() is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// - StridedLayoutMapping meets the layout mapping requirements ([mdspan.layout.policy.reqmts]),
|
||||
// - other.stride(r) > 0 is true for every rank index r of extents(),
|
||||
// - other.required_span_size() is representable as a value of type index_type ([basic.fundamental]), and
|
||||
// - OFFSET(other) == 0 is true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes extents_ with other.extents(), and for all d in the range [0, rank_),
|
||||
// direct-non-list-initializes strides_[d] with other.stride(d).
|
||||
//
|
||||
// Remarks: The expression inside explicit is equivalent to:
|
||||
// - !(is_convertible_v<typename StridedLayoutMapping::extents_type, extents_type> &&
|
||||
// (is-mapping-of<layout_left, LayoutStrideMapping> ||
|
||||
// is-mapping-of<layout_right, LayoutStrideMapping> ||
|
||||
// is-mapping-of<layout_stride, LayoutStrideMapping>))
|
||||
|
||||
#include <mdspan>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../CustomTestLayouts.h"
|
||||
|
||||
template <bool implicit, class FromL, class ToE, class FromE>
|
||||
constexpr void test_conversion(FromE src_exts) {
|
||||
using To = std::layout_stride::mapping<ToE>;
|
||||
using From = typename FromL::template mapping<FromE>;
|
||||
|
||||
From src([&]() {
|
||||
if constexpr (std::is_same_v<FromL, std::layout_stride>) {
|
||||
// just construct some strides which aren't layout_left/layout_right
|
||||
std::array<size_t, FromE::rank()> strides;
|
||||
size_t stride = 2;
|
||||
for (size_t r = 0; r < FromE::rank(); r++) {
|
||||
strides[r] = stride;
|
||||
stride *= src_exts.extent(r);
|
||||
}
|
||||
return From(src_exts, strides);
|
||||
} else {
|
||||
return From(src_exts);
|
||||
}
|
||||
}());
|
||||
|
||||
ASSERT_NOEXCEPT(To(src));
|
||||
To dest(src);
|
||||
assert(dest == src);
|
||||
|
||||
if constexpr (implicit) {
|
||||
To dest_implicit = src;
|
||||
assert(dest_implicit == src);
|
||||
} else {
|
||||
assert((!std::is_convertible_v<From, To>));
|
||||
}
|
||||
}
|
||||
|
||||
template <class FromL, class T1, class T2>
|
||||
constexpr void test_conversion() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
constexpr bool idx_convertible =
|
||||
static_cast<size_t>(std::numeric_limits<T1>::max()) >= static_cast<size_t>(std::numeric_limits<T2>::max());
|
||||
constexpr bool l_convertible =
|
||||
std::is_same_v<FromL, std::layout_right> || std::is_same_v<FromL, std::layout_left> ||
|
||||
std::is_same_v<FromL, std::layout_stride>;
|
||||
constexpr bool idx_l_convertible = idx_convertible && l_convertible;
|
||||
|
||||
// clang-format off
|
||||
// adding extents convertibility expectation
|
||||
test_conversion<idx_l_convertible && true, FromL, std::extents<T1>>(std::extents<T2>());
|
||||
test_conversion<idx_l_convertible && true, FromL, std::extents<T1, D>>(std::extents<T2, D>(0));
|
||||
test_conversion<idx_l_convertible && true, FromL, std::extents<T1, D>>(std::extents<T2, D>(5));
|
||||
test_conversion<idx_l_convertible && false, FromL, std::extents<T1, 5>>(std::extents<T2, D>(5));
|
||||
test_conversion<idx_l_convertible && true, FromL, std::extents<T1, 5>>(std::extents<T2, 5>());
|
||||
test_conversion<idx_l_convertible && false, FromL, std::extents<T1, 5, D>>(std::extents<T2, D, D>(5, 5));
|
||||
test_conversion<idx_l_convertible && true, FromL, std::extents<T1, D, D>>(std::extents<T2, D, D>(5, 5));
|
||||
test_conversion<idx_l_convertible && true, FromL, std::extents<T1, D, D>>(std::extents<T2, D, 7>(5));
|
||||
test_conversion<idx_l_convertible && true, FromL, std::extents<T1, 5, 7>>(std::extents<T2, 5, 7>());
|
||||
test_conversion<idx_l_convertible && false, FromL, std::extents<T1, 5, D, 8, D, D>>(std::extents<T2, D, D, 8, 9, 1>(5, 7));
|
||||
test_conversion<idx_l_convertible && true, FromL, std::extents<T1, D, D, D, D, D>>(
|
||||
std::extents<T2, D, D, D, D, D>(5, 7, 8, 9, 1));
|
||||
test_conversion<idx_l_convertible && true, FromL, std::extents<T1, D, D, 8, 9, D>>(std::extents<T2, D, 7, 8, 9, 1>(5));
|
||||
test_conversion<idx_l_convertible && true, FromL, std::extents<T1, 5, 7, 8, 9, 1>>(std::extents<T2, 5, 7, 8, 9, 1>());
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
template <class IdxT, size_t... Extents>
|
||||
using ToM = typename std::layout_stride::template mapping<std::extents<IdxT, Extents...>>;
|
||||
|
||||
template <class FromL, class IdxT, size_t... Extents>
|
||||
using FromM = typename FromL::template mapping<std::extents<IdxT, Extents...>>;
|
||||
|
||||
template <class FromL>
|
||||
constexpr void test_no_implicit_conversion() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
// Sanity check that one static to dynamic conversion works
|
||||
static_assert(std::is_constructible_v<ToM<int, D>, FromM<FromL, int, 5>>);
|
||||
static_assert(std::is_convertible_v<FromM<FromL, int, 5>, ToM<int, D>>);
|
||||
|
||||
// Check that dynamic to static conversion only works explicitly
|
||||
static_assert(std::is_constructible_v<ToM<int, 5>, FromM<FromL, int, D>>);
|
||||
static_assert(!std::is_convertible_v<FromM<FromL, int, D>, ToM<int, 5>>);
|
||||
|
||||
// Sanity check that one static to dynamic conversion works
|
||||
static_assert(std::is_constructible_v<ToM<int, D, 7>, FromM<FromL, int, 5, 7>>);
|
||||
static_assert(std::is_convertible_v<FromM<FromL, int, 5, 7>, ToM<int, D, 7>>);
|
||||
|
||||
// Check that dynamic to static conversion only works explicitly
|
||||
static_assert(std::is_constructible_v<ToM<int, 5, 7>, FromM<FromL, int, D, 7>>);
|
||||
static_assert(!std::is_convertible_v<FromM<FromL, int, D, 7>, ToM<int, 5, 7>>);
|
||||
|
||||
// Sanity check that smaller index_type to larger index_type conversion works
|
||||
static_assert(std::is_constructible_v<ToM<size_t, 5>, FromM<FromL, int, 5>>);
|
||||
static_assert(std::is_convertible_v<FromM<FromL, int, 5>, ToM<size_t, 5>>);
|
||||
|
||||
// Check that larger index_type to smaller index_type conversion works explicitly only
|
||||
static_assert(std::is_constructible_v<ToM<int, 5>, FromM<FromL, size_t, 5>>);
|
||||
static_assert(!std::is_convertible_v<FromM<FromL, size_t, 5>, ToM<int, 5>>);
|
||||
}
|
||||
|
||||
template <class FromL>
|
||||
constexpr void test_rank_mismatch() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
static_assert(!std::is_constructible_v<ToM<int, D>, FromM<FromL, int>>);
|
||||
static_assert(!std::is_constructible_v<ToM<int>, FromM<FromL, int, D, D>>);
|
||||
static_assert(!std::is_constructible_v<ToM<int, D>, FromM<FromL, int, D, D>>);
|
||||
static_assert(!std::is_constructible_v<ToM<int, D, D, D>, FromM<FromL, int, D, D>>);
|
||||
}
|
||||
|
||||
template <class FromL>
|
||||
constexpr void test_static_extent_mismatch() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
static_assert(!std::is_constructible_v<ToM<int, D, 5>, FromM<FromL, int, D, 4>>);
|
||||
static_assert(!std::is_constructible_v<ToM<int, 5>, FromM<FromL, int, 4>>);
|
||||
static_assert(!std::is_constructible_v<ToM<int, 5, D>, FromM<FromL, int, 4, D>>);
|
||||
}
|
||||
|
||||
template <class FromL>
|
||||
constexpr void test_layout() {
|
||||
test_conversion<FromL, int, int>();
|
||||
test_conversion<FromL, int, size_t>();
|
||||
test_conversion<FromL, size_t, int>();
|
||||
test_conversion<FromL, size_t, long>();
|
||||
// the implicit convertibility test doesn't apply to non std::layouts
|
||||
if constexpr (!std::is_same_v<FromL, always_convertible_layout>)
|
||||
test_no_implicit_conversion<FromL>();
|
||||
test_rank_mismatch<FromL>();
|
||||
test_static_extent_mismatch<FromL>();
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test_layout<std::layout_right>();
|
||||
test_layout<std::layout_left>();
|
||||
test_layout<std::layout_stride>();
|
||||
test_layout<always_convertible_layout>();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// ADDITIONAL_COMPILE_FLAGS: -Wno-ctad-maybe-unsupported
|
||||
|
||||
// <mdspan>
|
||||
|
||||
#include <mdspan>
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// mdspan
|
||||
|
||||
// layout_stride::mapping does not have explicit deduction guides,
|
||||
// but implicit deduction guides for constructor taking extents and strides
|
||||
// should work
|
||||
|
||||
constexpr bool test() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
|
||||
ASSERT_SAME_TYPE(decltype(std::layout_stride::mapping(std::extents<int>(), std::array<unsigned, 0>())),
|
||||
std::layout_stride::template mapping<std::extents<int>>);
|
||||
ASSERT_SAME_TYPE(decltype(std::layout_stride::mapping(std::extents<int, 4>(), std::array<char, 1>{1})),
|
||||
std::layout_stride::template mapping<std::extents<int, 4>>);
|
||||
ASSERT_SAME_TYPE(decltype(std::layout_stride::mapping(std::extents<int, D>(), std::array<char, 1>{1})),
|
||||
std::layout_stride::template mapping<std::extents<int, D>>);
|
||||
ASSERT_SAME_TYPE(
|
||||
decltype(std::layout_stride::mapping(std::extents<unsigned, D, 3>(), std::array<int64_t, 2>{3, 100})),
|
||||
std::layout_stride::template mapping<std::extents<unsigned, D, 3>>);
|
||||
|
||||
ASSERT_SAME_TYPE(decltype(std::layout_stride::mapping(std::extents<int>(), std::span<unsigned, 0>())),
|
||||
std::layout_stride::template mapping<std::extents<int>>);
|
||||
ASSERT_SAME_TYPE(decltype(std::layout_stride::mapping(std::extents<int, 4>(), std::declval<std::span<char, 1>>())),
|
||||
std::layout_stride::template mapping<std::extents<int, 4>>);
|
||||
ASSERT_SAME_TYPE(decltype(std::layout_stride::mapping(std::extents<int, D>(), std::declval<std::span<char, 1>>())),
|
||||
std::layout_stride::template mapping<std::extents<int, D>>);
|
||||
ASSERT_SAME_TYPE(
|
||||
decltype(std::layout_stride::mapping(std::extents<unsigned, D, 3>(), std::declval<std::span<int64_t, 2>>())),
|
||||
std::layout_stride::template mapping<std::extents<unsigned, D, 3>>);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class Extents>
|
||||
// class layout_stride::mapping;
|
||||
|
||||
// If Extents is not a specialization of extents, then the program is
|
||||
// ill-formed.
|
||||
|
||||
// Mandates: If Extents::rank_dynamic() == 0 is true, then the size of the
|
||||
// multidimensional index space Extents() is representable as a value of type
|
||||
// typename Extents::index_type.
|
||||
|
||||
#include <mdspan>
|
||||
|
||||
void not_extents() {
|
||||
// expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}layout_stride::mapping template argument must be a specialization of extents}}
|
||||
[[maybe_unused]] std::layout_stride::mapping<void> mapping;
|
||||
}
|
||||
|
||||
void representable() {
|
||||
// expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}layout_stride::mapping product of static extents must be representable as index_type.}}
|
||||
[[maybe_unused]] std::layout_stride::mapping<std::extents<char, 20, 20>> mapping;
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// Test default iteration:
|
||||
//
|
||||
// template<class... Indices>
|
||||
// constexpr index_type operator()(Indices...) const noexcept;
|
||||
//
|
||||
// Constraints:
|
||||
// * sizeof...(Indices) == extents_type::rank() is true,
|
||||
// * (is_convertible_v<Indices, index_type> && ...) is true, and
|
||||
// * (is_nothrow_constructible_v<index_type, Indices> && ...) is true.
|
||||
//
|
||||
// Preconditions:
|
||||
// * extents_type::index-cast(i) is a multidimensional index in extents_.
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../ConvertibleToIntegral.h"
|
||||
|
||||
template <class Mapping, class... Indices>
|
||||
concept operator_constraints = requires(Mapping m, Indices... idxs) {
|
||||
{ std::is_same_v<decltype(m(idxs...)), typename Mapping::index_type> };
|
||||
};
|
||||
|
||||
template <class Mapping, class... Indices>
|
||||
requires(operator_constraints<Mapping, Indices...>)
|
||||
constexpr bool check_operator_constraints(Mapping m, Indices... idxs) {
|
||||
(void)m(idxs...);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Mapping, class... Indices>
|
||||
constexpr bool check_operator_constraints(Mapping, Indices...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class M, class... Args>
|
||||
constexpr void iterate_stride(M m, const std::array<int, M::extents_type::rank()>& strides, Args... args) {
|
||||
constexpr int r = static_cast<int>(M::extents_type::rank()) - 1 - static_cast<int>(sizeof...(Args));
|
||||
if constexpr (-1 == r) {
|
||||
ASSERT_NOEXCEPT(m(args...));
|
||||
size_t expected_val = [&]<size_t... Pos>(std::index_sequence<Pos...>) {
|
||||
return ((args * strides[Pos]) + ... + 0);
|
||||
}(std::make_index_sequence<M::extents_type::rank()>());
|
||||
assert(expected_val == static_cast<size_t>(m(args...)));
|
||||
} else {
|
||||
for (typename M::index_type i = 0; i < m.extents().extent(r); i++) {
|
||||
iterate_stride(m, strides, i, args...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class E, class... Args>
|
||||
constexpr void test_iteration(std::array<int, E::rank()> strides, Args... args) {
|
||||
using M = std::layout_stride::mapping<E>;
|
||||
M m(E(args...), strides);
|
||||
|
||||
iterate_stride(m, strides);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
test_iteration<std::extents<int>>(std::array<int, 0>{});
|
||||
test_iteration<std::extents<unsigned, D>>(std::array<int, 1>{2}, 1);
|
||||
test_iteration<std::extents<unsigned, D>>(std::array<int, 1>{3}, 7);
|
||||
test_iteration<std::extents<unsigned, 7>>(std::array<int, 1>{4});
|
||||
test_iteration<std::extents<unsigned, 7, 8>>(std::array<int, 2>{25, 3});
|
||||
test_iteration<std::extents<char, D, D, D, D>>(std::array<int, 4>{1, 1, 1, 1}, 1, 1, 1, 1);
|
||||
|
||||
// Check operator constraint for number of arguments
|
||||
static_assert(check_operator_constraints(
|
||||
std::layout_stride::mapping<std::extents<int, D>>(std::extents<int, D>(1), std::array{1}), 0));
|
||||
static_assert(!check_operator_constraints(
|
||||
std::layout_stride::mapping<std::extents<int, D>>(std::extents<int, D>(1), std::array{1}), 0, 0));
|
||||
|
||||
// Check operator constraint for convertibility of arguments to index_type
|
||||
static_assert(check_operator_constraints(
|
||||
std::layout_stride::mapping<std::extents<int, D>>(std::extents<int, D>(1), std::array{1}), IntType(0)));
|
||||
static_assert(!check_operator_constraints(
|
||||
std::layout_stride::mapping<std::extents<unsigned, D>>(std::extents<unsigned, D>(1), std::array{1}), IntType(0)));
|
||||
|
||||
// Check operator constraint for no-throw-constructibility of index_type from arguments
|
||||
static_assert(!check_operator_constraints(
|
||||
std::layout_stride::mapping<std::extents<unsigned char, D>>(std::extents<unsigned char, D>(1), std::array{1}),
|
||||
IntType(0)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr bool test_large() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
test_iteration<std::extents<int64_t, D, 8, D, D>>(std::array<int, 4>{2000, 2, 20, 200}, 7, 9, 10);
|
||||
test_iteration<std::extents<int64_t, D, 8, 1, D>>(std::array<int, 4>{2000, 20, 20, 200}, 7, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
// The large test iterates over ~10k loop indices.
|
||||
// With assertions enabled this triggered the maximum default limit
|
||||
// for steps in consteval expressions. Assertions roughly double the
|
||||
// total number of instructions, so this was already close to the maximum.
|
||||
test_large();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// constexpr bool is_exhaustive() const noexcept;
|
||||
//
|
||||
// Returns:
|
||||
// - true if rank_ is 0.
|
||||
// - Otherwise, true if there is a permutation P of the integers in the range [0, rank_) such that
|
||||
// stride(p0) equals 1, and stride(pi) equals stride(pi_1) * extents().extent(pi_1) for i in the
|
||||
// range [1, rank_), where pi is the ith element of P.
|
||||
// - Otherwise, false.
|
||||
|
||||
#include <mdspan>
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class E>
|
||||
constexpr void
|
||||
test_layout_mapping_stride(E ext, std::array<typename E::index_type, E::rank()> strides, bool exhaustive) {
|
||||
using M = std::layout_stride::template mapping<E>;
|
||||
M m(ext, strides);
|
||||
assert(m.is_exhaustive() == exhaustive);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
test_layout_mapping_stride(std::extents<int, 0>(), std::array<int, 1>{1}, true);
|
||||
test_layout_mapping_stride(std::extents<unsigned, D>(0), std::array<unsigned, 1>{3}, false);
|
||||
test_layout_mapping_stride(std::extents<int, 0, 3>(), std::array<int, 2>{6, 2}, true);
|
||||
test_layout_mapping_stride(std::extents<int, D, D>(3, 0), std::array<int, 2>{6, 2}, false);
|
||||
test_layout_mapping_stride(std::extents<int, D, D>(0, 0), std::array<int, 2>{6, 2}, false);
|
||||
test_layout_mapping_stride(
|
||||
std::extents<unsigned, D, D, D, D>(3, 3, 0, 3), std::array<unsigned, 4>{3, 1, 27, 9}, true);
|
||||
test_layout_mapping_stride(std::extents<int, D, D, D, D>(0, 3, 3, 3), std::array<int, 4>{3, 1, 27, 9}, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// namespace std {
|
||||
// template<class Extents>
|
||||
// class layout_stride::mapping {
|
||||
//
|
||||
// ...
|
||||
// static constexpr bool is_always_unique() noexcept { return true; }
|
||||
// static constexpr bool is_always_exhaustive() noexcept { return false; }
|
||||
// static constexpr bool is_always_strided() noexcept { return true; }
|
||||
//
|
||||
// static constexpr bool is_unique() noexcept { return true; }
|
||||
// static constexpr bool is_exhaustive() noexcept;
|
||||
// static constexpr bool is_strided() noexcept { return true; }
|
||||
// ...
|
||||
// };
|
||||
// }
|
||||
//
|
||||
//
|
||||
// layout_stride::mapping<E> is a trivially copyable type that models regular for each E.
|
||||
//
|
||||
// constexpr bool is_exhaustive() const noexcept;
|
||||
//
|
||||
// Returns:
|
||||
// - true if rank_ is 0.
|
||||
// - Otherwise, true if there is a permutation P of the integers in the range [0, rank_) such that
|
||||
// stride(p0) equals 1, and stride(pi) equals stride(pi_1) * extents().extent(pi_1) for i in the
|
||||
// range [1, rank_), where pi is the ith element of P.
|
||||
// - Otherwise, false.
|
||||
|
||||
#include <mdspan>
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class E>
|
||||
constexpr void
|
||||
test_layout_mapping_stride(E ext, std::array<typename E::index_type, E::rank()> strides, bool exhaustive) {
|
||||
using M = std::layout_stride::template mapping<E>;
|
||||
M m(ext, strides);
|
||||
const M c_m = m;
|
||||
assert(m.strides() == strides);
|
||||
assert(c_m.strides() == strides);
|
||||
assert(m.extents() == ext);
|
||||
assert(c_m.extents() == ext);
|
||||
assert(M::is_unique() == true);
|
||||
assert(m.is_exhaustive() == exhaustive);
|
||||
assert(c_m.is_exhaustive() == exhaustive);
|
||||
assert(M::is_strided() == true);
|
||||
assert(M::is_always_unique() == true);
|
||||
assert(M::is_always_exhaustive() == false);
|
||||
assert(M::is_always_strided() == true);
|
||||
|
||||
ASSERT_NOEXCEPT(m.strides());
|
||||
ASSERT_NOEXCEPT(c_m.strides());
|
||||
ASSERT_NOEXCEPT(m.extents());
|
||||
ASSERT_NOEXCEPT(c_m.extents());
|
||||
ASSERT_NOEXCEPT(M::is_unique());
|
||||
ASSERT_NOEXCEPT(m.is_exhaustive());
|
||||
ASSERT_NOEXCEPT(c_m.is_exhaustive());
|
||||
ASSERT_NOEXCEPT(M::is_strided());
|
||||
ASSERT_NOEXCEPT(M::is_always_unique());
|
||||
ASSERT_NOEXCEPT(M::is_always_exhaustive());
|
||||
ASSERT_NOEXCEPT(M::is_always_strided());
|
||||
|
||||
for (typename E::rank_type r = 0; r < E::rank(); r++) {
|
||||
assert(m.stride(r) == strides[r]);
|
||||
assert(c_m.stride(r) == strides[r]);
|
||||
ASSERT_NOEXCEPT(m.stride(r));
|
||||
ASSERT_NOEXCEPT(c_m.stride(r));
|
||||
}
|
||||
|
||||
typename E::index_type expected_size = 1;
|
||||
for (typename E::rank_type r = 0; r < E::rank(); r++) {
|
||||
if (ext.extent(r) == 0) {
|
||||
expected_size = 0;
|
||||
break;
|
||||
}
|
||||
expected_size += (ext.extent(r) - 1) * static_cast<typename E::index_type>(strides[r]);
|
||||
}
|
||||
assert(m.required_span_size() == expected_size);
|
||||
assert(c_m.required_span_size() == expected_size);
|
||||
ASSERT_NOEXCEPT(m.required_span_size());
|
||||
ASSERT_NOEXCEPT(c_m.required_span_size());
|
||||
|
||||
static_assert(std::is_trivially_copyable_v<M>);
|
||||
static_assert(std::regular<M>);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
test_layout_mapping_stride(std::extents<int>(), std::array<int, 0>{}, true);
|
||||
test_layout_mapping_stride(std::extents<char, 4, 5>(), std::array<char, 2>{1, 4}, true);
|
||||
test_layout_mapping_stride(std::extents<char, 4, 5>(), std::array<char, 2>{1, 5}, false);
|
||||
test_layout_mapping_stride(std::extents<unsigned, D, 4>(7), std::array<unsigned, 2>{20, 2}, false);
|
||||
test_layout_mapping_stride(std::extents<size_t, D, D, D, D>(3, 3, 3, 3), std::array<size_t, 4>{3, 1, 9, 27}, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// Let REQUIRED-SPAN-SIZE(e, strides) be:
|
||||
// - 1, if e.rank() == 0 is true,
|
||||
// - otherwise 0, if the size of the multidimensional index space e is 0,
|
||||
// - otherwise 1 plus the sum of products of (e.extent(r) - 1) and strides[r] for all r in the range [0, e.rank()).
|
||||
|
||||
// constexpr index_type required_span_size() const noexcept;
|
||||
//
|
||||
// Returns: REQUIRED-SPAN-SIZE(extents(), strides_).
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class E>
|
||||
constexpr void test_required_span_size(E e, std::array<int, E::rank()> strides, typename E::index_type expected_size) {
|
||||
using M = std::layout_stride::mapping<E>;
|
||||
const M m(e, strides);
|
||||
|
||||
ASSERT_NOEXCEPT(m.required_span_size());
|
||||
assert(m.required_span_size() == expected_size);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
test_required_span_size(std::extents<int>(), std::array<int, 0>{}, 1);
|
||||
test_required_span_size(std::extents<unsigned, D>(0), std::array<int, 1>{5}, 0);
|
||||
test_required_span_size(std::extents<unsigned, D>(1), std::array<int, 1>{5}, 1);
|
||||
test_required_span_size(std::extents<unsigned, D>(7), std::array<int, 1>{5}, 31);
|
||||
test_required_span_size(std::extents<unsigned, 7>(), std::array<int, 1>{5}, 31);
|
||||
test_required_span_size(std::extents<unsigned, 7, 8>(), std::array<int, 2>{20, 2}, 135);
|
||||
test_required_span_size(
|
||||
std::extents<int64_t, D, 8, D, D>(7, 9, 10), std::array<int, 4>{1, 7, 7 * 8, 7 * 8 * 9}, 5040);
|
||||
test_required_span_size(std::extents<int64_t, 1, 8, D, D>(9, 10), std::array<int, 4>{1, 7, 7 * 8, 7 * 8 * 9}, 5034);
|
||||
test_required_span_size(std::extents<int64_t, 1, 0, D, D>(9, 10), std::array<int, 4>{1, 7, 7 * 8, 7 * 8 * 9}, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// A type M meets the layout mapping requirements if
|
||||
// - M models copyable and equality_comparable,
|
||||
// - is_nothrow_move_constructible_v<M> is true,
|
||||
// - is_nothrow_move_assignable_v<M> is true,
|
||||
// - is_nothrow_swappable_v<M> is true, and
|
||||
//
|
||||
// the following types and expressions are well-formed and have the specified semantics.
|
||||
//
|
||||
// typename M::extents_type
|
||||
// Result: A type that is a specialization of extents.
|
||||
//
|
||||
// typename M::index_type
|
||||
// Result: typename M::extents_type::index_type.
|
||||
//
|
||||
// typename M::rank_type
|
||||
// Result: typename M::extents_type::rank_type.
|
||||
//
|
||||
// typename M::layout_type
|
||||
// Result: A type MP that meets the layout mapping policy requirements ([mdspan.layout.policy.reqmts]) and for which is-mapping-of<MP, M> is true.
|
||||
//
|
||||
// m.extents()
|
||||
// Result: const typename M::extents_type&
|
||||
//
|
||||
// m(i...)
|
||||
// Result: typename M::index_type
|
||||
// Returns: A nonnegative integer less than numeric_limits<typename M::index_type>::max() and less than or equal to numeric_limits<size_t>::max().
|
||||
//
|
||||
// m(i...) == m(static_cast<typename M::index_type>(i)...)
|
||||
// Result: bool
|
||||
// Returns: true
|
||||
//
|
||||
// m.required_span_size()
|
||||
// Result: typename M::index_type
|
||||
// Returns: If the size of the multidimensional index space m.extents() is 0, then 0, else 1 plus the maximum value of m(i...) for all i.
|
||||
//
|
||||
// m.is_unique()
|
||||
// Result: bool
|
||||
// Returns: true only if for every i and j where (i != j || ...) is true, m(i...) != m(j...) is true.
|
||||
//
|
||||
// m.is_exhaustive()
|
||||
// Result: bool
|
||||
// Returns: true only if for all k in the range [0, m.required_span_size()) there exists an i such that m(i...) equals k.
|
||||
//
|
||||
// m.is_strided()
|
||||
// Result: bool
|
||||
// Returns: true only if for every rank index r of m.extents() there exists an integer
|
||||
// sr such that, for all i where (i+dr) is a multidimensional index in m.extents() ([mdspan.overview]),
|
||||
// m((i + dr)...) - m(i...) equals sr
|
||||
//
|
||||
// m.stride(r)
|
||||
// Preconditions: m.is_strided() is true.
|
||||
// Result: typename M::index_type
|
||||
// Returns: sr as defined in m.is_strided() above.
|
||||
//
|
||||
// M::is_always_unique()
|
||||
// Result: A constant expression ([expr.const]) of type bool.
|
||||
// Returns: true only if m.is_unique() is true for all possible objects m of type M.
|
||||
//
|
||||
// M::is_always_exhaustive()
|
||||
// Result: A constant expression ([expr.const]) of type bool.
|
||||
// Returns: true only if m.is_exhaustive() is true for all possible objects m of type M.
|
||||
//
|
||||
// M::is_always_strided()
|
||||
// Result: A constant expression ([expr.const]) of type bool.
|
||||
// Returns: true only if m.is_strided() is true for all possible objects m of type M.
|
||||
|
||||
#include <mdspan>
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Common requirements of all layout mappings
|
||||
template <class M, size_t... Idxs>
|
||||
void test_mapping_requirements(std::index_sequence<Idxs...>) {
|
||||
using E = typename M::extents_type;
|
||||
static_assert(std::__mdspan_detail::__is_extents_v<E>);
|
||||
static_assert(std::is_copy_constructible_v<M>);
|
||||
static_assert(std::is_nothrow_move_constructible_v<M>);
|
||||
static_assert(std::is_nothrow_move_assignable_v<M>);
|
||||
static_assert(std::is_nothrow_swappable_v<M>);
|
||||
ASSERT_SAME_TYPE(typename M::index_type, typename E::index_type);
|
||||
ASSERT_SAME_TYPE(typename M::size_type, typename E::size_type);
|
||||
ASSERT_SAME_TYPE(typename M::rank_type, typename E::rank_type);
|
||||
ASSERT_SAME_TYPE(typename M::layout_type, std::layout_stride);
|
||||
ASSERT_SAME_TYPE(typename M::layout_type::template mapping<E>, M);
|
||||
static_assert(std::is_same_v<decltype(std::declval<M>().extents()), const E&>);
|
||||
static_assert(std::is_same_v<decltype(std::declval<M>().strides()), std::array<typename M::index_type, E::rank()>>);
|
||||
static_assert(std::is_same_v<decltype(std::declval<M>()(Idxs...)), typename M::index_type>);
|
||||
static_assert(std::is_same_v<decltype(std::declval<M>().required_span_size()), typename M::index_type>);
|
||||
static_assert(std::is_same_v<decltype(std::declval<M>().is_unique()), bool>);
|
||||
static_assert(std::is_same_v<decltype(std::declval<M>().is_exhaustive()), bool>);
|
||||
static_assert(std::is_same_v<decltype(std::declval<M>().is_strided()), bool>);
|
||||
static_assert(std::is_same_v<decltype(std::declval<M>().stride(0)), typename M::index_type>);
|
||||
static_assert(std::is_same_v<decltype(M::is_always_unique()), bool>);
|
||||
static_assert(std::is_same_v<decltype(M::is_always_exhaustive()), bool>);
|
||||
static_assert(std::is_same_v<decltype(M::is_always_strided()), bool>);
|
||||
}
|
||||
|
||||
template <class L, class E>
|
||||
void test_layout_mapping_requirements() {
|
||||
using M = typename L::template mapping<E>;
|
||||
test_mapping_requirements<M>(std::make_index_sequence<E::rank()>());
|
||||
}
|
||||
|
||||
template <class E>
|
||||
void test_layout_mapping_stride() {
|
||||
test_layout_mapping_requirements<std::layout_stride, E>();
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
test_layout_mapping_stride<std::extents<int>>();
|
||||
test_layout_mapping_stride<std::extents<char, 4, 5>>();
|
||||
test_layout_mapping_stride<std::extents<unsigned, D, 4>>();
|
||||
test_layout_mapping_stride<std::extents<size_t, D, D, D, D>>();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// constexpr index_type stride(rank_type i) const noexcept;
|
||||
//
|
||||
// Constraints: extents_type::rank() > 0 is true.
|
||||
//
|
||||
// Preconditions: i < extents_type::rank() is true.
|
||||
//
|
||||
// Returns: extents().rev-prod-of-extents(i).
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class E, class... Args>
|
||||
constexpr void test_stride(std::array<typename E::index_type, E::rank()> strides, Args... args) {
|
||||
using M = std::layout_stride::mapping<E>;
|
||||
M m(E(args...), strides);
|
||||
|
||||
ASSERT_NOEXCEPT(m.stride(0));
|
||||
for (size_t r = 0; r < E::rank(); r++)
|
||||
assert(strides[r] == m.stride(r));
|
||||
|
||||
ASSERT_NOEXCEPT(m.strides());
|
||||
auto strides_out = m.strides();
|
||||
static_assert(std::is_same_v<decltype(strides_out), std::array<typename E::index_type, E::rank()>>);
|
||||
for (size_t r = 0; r < E::rank(); r++)
|
||||
assert(strides[r] == strides_out[r]);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
constexpr size_t D = std::dynamic_extent;
|
||||
test_stride<std::extents<unsigned, D>>(std::array<unsigned, 1>{1}, 7);
|
||||
test_stride<std::extents<unsigned, 7>>(std::array<unsigned, 1>{1});
|
||||
test_stride<std::extents<unsigned, 7, 8>>(std::array<unsigned, 2>{8, 1});
|
||||
test_stride<std::extents<int64_t, D, 8, D, D>>(std::array<int64_t, 4>{720, 90, 10, 1}, 7, 9, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <class H, class M, class A>
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <class ToMDS, class FromMDS>
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
#include <mdspan>
|
||||
#include "CustomTestAccessors.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
|
||||
void cant_construct_data_handle_type() {
|
||||
int data;
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <class H, class M, class A>
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <bool hc, bool mc, bool ac, class H, class M, class A>
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
#include "../ConvertibleToIntegral.h"
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <class Extents, size_t... Idxs>
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <bool mec, bool ac, class H, class M, class A>
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <class MDS, class... Args>
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <bool ac, class H, class M, class A>
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <class H, class M, class A>
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
#include "../ConvertibleToIntegral.h"
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <class Extents, size_t... Idxs>
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <class H, class M, class A>
|
||||
|
@ -55,7 +55,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <class H, class M, class A>
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../ConvertibleToIntegral.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
|
||||
// Clang 16 does not support argument packs as input to operator []
|
||||
#if defined(__clang_major__) && __clang_major__ < 17
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
|
||||
template <class H, class M, class A>
|
||||
|
@ -58,7 +58,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
|
||||
template <class H, class M, class A>
|
||||
constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) {
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
|
||||
template <class MDS>
|
||||
constexpr void test_swap(MDS a, MDS b) {
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
#include "CustomTestAccessors.h"
|
||||
#include "CustomTestLayouts.h"
|
||||
#include "../CustomTestLayouts.h"
|
||||
|
||||
// Calculated expected size of an mdspan
|
||||
// Note this expectes that only default_accessor is empty
|
||||
|
@ -65,17 +65,11 @@
|
||||
|
||||
#elif TEST_STD_VER == 23
|
||||
|
||||
# if !defined(_LIBCPP_VERSION)
|
||||
# ifndef __cpp_lib_mdspan
|
||||
# error "__cpp_lib_mdspan should be defined in c++23"
|
||||
# endif
|
||||
# if __cpp_lib_mdspan != 202207L
|
||||
# error "__cpp_lib_mdspan should have the value 202207L in c++23"
|
||||
# endif
|
||||
# else // _LIBCPP_VERSION
|
||||
# ifdef __cpp_lib_mdspan
|
||||
# error "__cpp_lib_mdspan should not be defined because it is unimplemented in libc++!"
|
||||
# endif
|
||||
# ifndef __cpp_lib_mdspan
|
||||
# error "__cpp_lib_mdspan should be defined in c++23"
|
||||
# endif
|
||||
# if __cpp_lib_mdspan != 202207L
|
||||
# error "__cpp_lib_mdspan should have the value 202207L in c++23"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_submdspan
|
||||
@ -84,17 +78,11 @@
|
||||
|
||||
#elif TEST_STD_VER > 23
|
||||
|
||||
# if !defined(_LIBCPP_VERSION)
|
||||
# ifndef __cpp_lib_mdspan
|
||||
# error "__cpp_lib_mdspan should be defined in c++26"
|
||||
# endif
|
||||
# if __cpp_lib_mdspan != 202207L
|
||||
# error "__cpp_lib_mdspan should have the value 202207L in c++26"
|
||||
# endif
|
||||
# else // _LIBCPP_VERSION
|
||||
# ifdef __cpp_lib_mdspan
|
||||
# error "__cpp_lib_mdspan should not be defined because it is unimplemented in libc++!"
|
||||
# endif
|
||||
# ifndef __cpp_lib_mdspan
|
||||
# error "__cpp_lib_mdspan should be defined in c++26"
|
||||
# endif
|
||||
# if __cpp_lib_mdspan != 202207L
|
||||
# error "__cpp_lib_mdspan should have the value 202207L in c++26"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_VERSION)
|
||||
|
@ -4804,17 +4804,11 @@
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_VERSION)
|
||||
# ifndef __cpp_lib_mdspan
|
||||
# error "__cpp_lib_mdspan should be defined in c++23"
|
||||
# endif
|
||||
# if __cpp_lib_mdspan != 202207L
|
||||
# error "__cpp_lib_mdspan should have the value 202207L in c++23"
|
||||
# endif
|
||||
# else // _LIBCPP_VERSION
|
||||
# ifdef __cpp_lib_mdspan
|
||||
# error "__cpp_lib_mdspan should not be defined because it is unimplemented in libc++!"
|
||||
# endif
|
||||
# ifndef __cpp_lib_mdspan
|
||||
# error "__cpp_lib_mdspan should be defined in c++23"
|
||||
# endif
|
||||
# if __cpp_lib_mdspan != 202207L
|
||||
# error "__cpp_lib_mdspan should have the value 202207L in c++23"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_AVAILABILITY_HAS_NO_PMR)
|
||||
@ -6345,17 +6339,11 @@
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_VERSION)
|
||||
# ifndef __cpp_lib_mdspan
|
||||
# error "__cpp_lib_mdspan should be defined in c++26"
|
||||
# endif
|
||||
# if __cpp_lib_mdspan != 202207L
|
||||
# error "__cpp_lib_mdspan should have the value 202207L in c++26"
|
||||
# endif
|
||||
# else // _LIBCPP_VERSION
|
||||
# ifdef __cpp_lib_mdspan
|
||||
# error "__cpp_lib_mdspan should not be defined because it is unimplemented in libc++!"
|
||||
# endif
|
||||
# ifndef __cpp_lib_mdspan
|
||||
# error "__cpp_lib_mdspan should be defined in c++26"
|
||||
# endif
|
||||
# if __cpp_lib_mdspan != 202207L
|
||||
# error "__cpp_lib_mdspan should have the value 202207L in c++26"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_AVAILABILITY_HAS_NO_PMR)
|
||||
|
@ -2654,7 +2654,6 @@ libcxx/test/std/containers/views/mdspan/layout_left/index_operator.pass.cpp
|
||||
libcxx/test/std/containers/views/mdspan/layout_left/required_span_size.pass.cpp
|
||||
libcxx/test/std/containers/views/mdspan/layout_right/index_operator.pass.cpp
|
||||
libcxx/test/std/containers/views/mdspan/layout_right/required_span_size.pass.cpp
|
||||
libcxx/test/std/containers/views/mdspan/mdspan/CustomTestLayouts.h
|
||||
libcxx/test/std/containers/views/mdspan/mdspan/conversion.pass.cpp
|
||||
libcxx/test/std/containers/views/mdspan/mdspan/types.pass.cpp
|
||||
libcxx/test/std/containers/views/views.span/range_concept_conformance.compile.pass.cpp
|
||||
|
@ -689,7 +689,6 @@ feature_test_macros = [
|
||||
"name": "__cpp_lib_mdspan",
|
||||
"values": {"c++23": 202207},
|
||||
"headers": ["mdspan"],
|
||||
"unimplemented": True,
|
||||
},
|
||||
{
|
||||
"name": "__cpp_lib_memory_resource",
|
||||
|
Loading…
x
Reference in New Issue
Block a user