5#ifndef DUNE_COMMON_STD_EXTENTS_HH
6#define DUNE_COMMON_STD_EXTENTS_HH
12#if __has_include(<version>)
16#include <dune/common/indices.hh>
17#include <dune/common/std/no_unique_address.hh>
18#include <dune/common/std/span.hh>
19#include <dune/common/std/impl/fwd_layouts.hh>
24template <
class IndexType, std::
size_t n>
25struct DynamicExtentsArray
27 using type = std::array<IndexType,n>;
30template <
class IndexType>
31struct DynamicExtentsArray<IndexType,0>
35 IndexType operator[](std::size_t )
const {
return 0; }
53template <
class IndexType, std::size_t... exts>
56 static_assert(std::is_integral_v<IndexType>);
59 static constexpr std::size_t rank_ =
sizeof...(exts);
63 using array_type = std::array<std::size_t,rank_>;
66 static constexpr std::array<std::size_t,rank_+1> make_dynamic_index()
68 std::array<std::size_t,rank_+1> di{{}};
69 for (std::size_t i = 0; i < rank_; ++i)
76 static constexpr std::array<std::size_t,rank_+1> dynamic_index_{make_dynamic_index()};
79 using rank_type = std::size_t;
80 using index_type = IndexType;
81 using size_type = std::make_unsigned_t<index_type>;
88 static constexpr rank_type
rank () noexcept {
return rank_; }
91 static constexpr rank_type
rank_dynamic () noexcept {
return rank_dynamic_; }
97 return array_type{exts...}[r];
101 constexpr index_type
extent (rank_type r)
const noexcept
105 return index_type(e);
107 return dynamic_extents_[dynamic_index_[r]];
121 template <class... IndexTypes,
122 std::enable_if_t<(... &&
std::is_convertible_v<IndexTypes,index_type>),
int> = 0,
123 std::enable_if_t<(sizeof...(IndexTypes) ==
rank() || sizeof...(IndexTypes) ==
rank_dynamic()),
int> = 0,
124 std::enable_if_t<(... &&
std::is_nothrow_constructible_v<index_type, IndexTypes>),
int> = 0>
125 constexpr explicit
extents (IndexTypes... e) noexcept
127 init_dynamic_extents<
sizeof...(e)>(std::array<index_type,
sizeof...(e)>{index_type(e)...});
132 template <
class I, std::size_t N,
133 std::enable_if_t<std::is_convertible_v<I, index_type>,
int> = 0,
135 #
if __cpp_conditional_explicit >= 201806L
138 constexpr extents (
const std::array<I,N>& e)
noexcept
140 init_dynamic_extents<N>(e);
145 template <
class I, std::size_t N,
146 std::enable_if_t<std::is_convertible_v<I, index_type>,
int> = 0,
148 std::enable_if_t<std::is_nothrow_constructible_v<index_type, const I&>,
int> = 0>
149 #
if __cpp_conditional_explicit >= 201806L
154 init_dynamic_extents<N>(e);
157 template <
class I, std::size_t... e,
158 std::enable_if_t<(
sizeof...(e) ==
rank()),
int> = 0,
160 #if __cpp_conditional_explicit >= 201806L
167 init_dynamic_extents<
sizeof...(e)>(as_array(other));
174 template <
class OtherIndexType, std::size_t... otherExts>
177 if (a.rank() != b.rank())
179 using I = std::common_type_t<index_type, OtherIndexType>;
180 for (rank_type i = 0; i <
rank(); ++i)
181 if (I(a.extent(i)) != I(b.extent(i)))
189 constexpr size_type product () const noexcept
192 for (rank_type i = 0; i <
rank(); ++i)
198 template <
class OtherIndexType, std::size_t... otherExts>
199 static constexpr std::array<index_type,
sizeof...(otherExts)>
203 return std::array<index_type,
sizeof...(otherExts)>{index_type(e.extent(ii))...}; },
204 std::make_index_sequence<
sizeof...(otherExts)>{});
208 template <std::
size_t N,
class Container>
209 constexpr void init_dynamic_extents (
const Container& e)
noexcept
215 dynamic_extents_[i] = e[i];
217 assert(e.size() ==
rank());
218 for (rank_type i = 0, j = 0; i <
rank(); ++i) {
220 dynamic_extents_[j++] = e[i];
228 using dynamic_extents_type =
typename Impl::DynamicExtentsArray<index_type,
rank_dynamic()>::type;
229 DUNE_NO_UNIQUE_ADDRESS dynamic_extents_type dynamic_extents_;
231 template <
class, std::size_t...>
friend class extents;
232 friend struct layout_left;
233 friend struct layout_right;
234 friend struct layout_stride;
240template <
class IndexType,
class Seq>
243template <
class IndexType, std::size_t... I>
244struct DExtentsImpl<IndexType,
std::integer_sequence<std::size_t,I...>>
257template <
class IndexType, std::
size_t R>
258using dextents =
typename Impl::DExtentsImpl<IndexType, std::make_integer_sequence<std::size_t,R>>::type;
Multidimensional index space with dynamic and static extents.
Definition: extents.hh:55
static constexpr rank_type rank_dynamic() noexcept
The number of dimensions with dynamic extent.
Definition: extents.hh:91
constexpr extents() noexcept=default
The default constructor requires that all exts are not Std::dynamic_extent.
static constexpr rank_type rank() noexcept
The total number of dimensions.
Definition: extents.hh:88
friend constexpr bool operator==(const extents &a, const extents< OtherIndexType, otherExts... > &b) noexcept
Compare two extents by their rank and all individual extents.
Definition: extents.hh:175
static constexpr std::size_t static_extent(rank_type r) noexcept
Return the static extent of dimension r or Std::dynamic_extent
Definition: extents.hh:94
constexpr index_type extent(rank_type r) const noexcept
Return the extent of dimension i
Definition: extents.hh:101
A contiguous sequence of elements with static or dynamic extent.
Definition: span.hh:126
decltype(auto) constexpr unpackIntegerSequence(F &&f, std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition: indices.hh:124
typename Impl::DExtentsImpl< IndexType, std::make_integer_sequence< std::size_t, R > >::type dextents
Alias of extents of given rank R and purely dynamic extents. See [mdspan.extents.dextents].
Definition: extents.hh:258
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:484
Namespace for features backported from new C++ standards.
Definition: algorithm.hh:19
constexpr std::size_t dynamic_extent
A constant of type std::size_t that is used to differentiate std::span of static and dynamic extent.
Definition: span.hh:26