5#ifndef DUNE_COMMON_STD_MDARRAY_HH
6#define DUNE_COMMON_STD_MDARRAY_HH
14#if __has_include(<version>)
18#include <dune/common/indices.hh>
20#include <dune/common/std/default_accessor.hh>
21#include <dune/common/std/mdspan.hh>
22#include <dune/common/std/memory.hh>
23#include <dune/common/std/no_unique_address.hh>
24#include <dune/common/std/span.hh>
25#include <dune/common/std/impl/containerconstructiontraits.hh>
67template <
class Element,
class Extents,
class LayoutPolicy = Std::layout_right,
68 class Container = std::vector<Element>>
71 template <
class,
class,
class,
class>
friend class mdarray;
73 static_assert(std::is_object_v<Element>);
74 static_assert(!std::is_abstract_v<Element>);
75 static_assert(!std::is_array_v<Element>);
76 static_assert(std::is_same_v<Element, typename Container::value_type>);
79 using element_type = Element;
80 using extents_type = Extents;
81 using layout_type = LayoutPolicy;
82 using container_type = Container;
84 using value_type = element_type;
85 using mapping_type =
typename layout_type::template mapping<extents_type>;
87 using index_type =
typename extents_type::index_type;
88 using size_type =
typename extents_type::size_type;
89 using rank_type =
typename extents_type::rank_type;
94 using pointer =
decltype(
Std::to_address(std::declval<container_type>().begin()));
95 using reference =
typename container_type::reference;
96 using const_pointer =
decltype(
Std::to_address(std::declval<container_type>().cbegin()));
97 using const_reference =
typename container_type::const_reference;
99 static_assert(std::is_constructible_v<mapping_type, extents_type>);
103 template <
class C,
class... Args>
104 static constexpr auto construct_container (Args&&... args)
105 ->
decltype(Impl::ContainerConstructionTraits<C>::construct(std::forward<Args>(args)...))
107 return Impl::ContainerConstructionTraits<C>::construct(std::forward<Args>(args)...);
115 template <
class E = extents_type,
class C = container_type,
class M = mapping_type,
116 std::enable_if_t<(E::rank_dynamic() != 0),
int> = 0,
117 std::enable_if_t<std::is_default_constructible_v<C>,
int> = 0,
118 std::enable_if_t<std::is_default_constructible_v<M>,
int> = 0>
130 template <
class... IndexTypes,
131 std::enable_if_t<(... && std::is_convertible_v<IndexTypes,index_type>),
int> = 0,
132 std::enable_if_t<std::is_constructible_v<extents_type,IndexTypes...>,
int> = 0,
133 std::enable_if_t<(... && std::is_nothrow_constructible_v<index_type,IndexTypes>),
int> = 0>
134 explicit constexpr mdarray (IndexTypes... exts)
135 :
mdarray(extents_type(index_type(
std::move(exts))...))
139 explicit constexpr mdarray (
const extents_type& e)
144 template <
class C = container_type,
145 decltype(construct_container<C>(std::declval<std::size_t>()),
bool{}) =
true>
146 explicit constexpr mdarray (
const mapping_type& m)
147 : container_(construct_container<C>(m.required_span_size()))
156 constexpr mdarray (
const extents_type& e,
const value_type& v)
161 template <
class C = container_type,
162 decltype(construct_container<C>(std::declval<std::size_t>(),std::declval<const value_type&>()),
bool{}) =
true>
163 constexpr mdarray (
const mapping_type& m,
const value_type& v)
164 : container_(construct_container<C>(m.required_span_size(), v))
173 template <
class E = extents_type,
174 std::enable_if_t<std::is_constructible_v<mapping_type,const E&>,
int> = 0>
175 constexpr mdarray (
const E& e,
const container_type& c)
181 template <
class E = extents_type,
182 std::enable_if_t<std::is_constructible_v<mapping_type,const E&>,
int> = 0>
183 constexpr mdarray (
const E& e, container_type&& c)
184 : container_(
std::move(c))
189 constexpr mdarray (
const mapping_type& m,
const container_type& c)
195 constexpr mdarray (
const mapping_type& m, container_type&& c)
196 : container_(
std::move(c))
205 template <
class OtherElementType,
class OtherExtents,
class OtherLayoutPolicy,
class OtherContainer,
206 std::enable_if_t<std::is_constructible_v<Container,const OtherContainer&>,
int> = 0,
207 std::enable_if_t<std::is_constructible_v<extents_type,OtherExtents>,
int> = 0,
208 std::enable_if_t<std::is_constructible_v<mapping_type,const typename OtherLayoutPolicy::template mapping<OtherExtents>&>,
int> = 0>
209 #if __cpp_conditional_explicit >= 201806L
211 !std::is_convertible_v<const typename OtherLayoutPolicy::template mapping<OtherExtents>&, mapping_type> ||
212 !std::is_convertible_v<const OtherContainer&, container_type>)
215 : container_(other.container_)
216 , mapping_(other.mapping_)
220 template <
class OtherElementType,
class OtherExtents,
class OtherLayoutPolicy,
class Accessor,
221 std::enable_if_t<std::is_constructible_v<value_type,typename Accessor::reference>,
int> = 0,
222 std::enable_if_t<std::is_assignable_v<typename Accessor::reference, value_type>,
int> = 0,
223 std::enable_if_t<std::is_constructible_v<mapping_type, const typename OtherLayoutPolicy::template mapping<OtherExtents>&>,
int> = 0,
224 decltype(construct_container<container_type>(std::declval<std::size_t>()),
bool{}) =
true>
225 #
if __cpp_conditional_explicit >= 201806L
227 !std::is_convertible_v<
const typename OtherLayoutPolicy::template mapping<OtherExtents>&, mapping_type> ||
228 !std::is_convertible_v<typename Accessor::reference, value_type>)
231 : container_(construct_container<container_type>(other.
size()))
234 init_from_mdspan(other);
242 template <
class Alloc,
243 std::enable_if_t<std::is_constructible_v<container_type, std::size_t, Alloc>,
int> = 0>
244 constexpr mdarray (
const extents_type& e,
const Alloc& a)
249 template <
class Alloc,
250 std::enable_if_t<std::is_constructible_v<container_type, std::size_t, Alloc>,
int> = 0>
251 constexpr mdarray (
const mapping_type& m,
const Alloc& a)
252 : container_(m.required_span_size(), a)
257 template <
class Alloc>
258 constexpr mdarray (
const extents_type& e,
const value_type& v,
const Alloc& a)
259 :
mdarray(mapping_type(e), v, a)
263 template <
class Alloc,
264 std::enable_if_t<std::is_constructible_v<container_type, std::size_t, value_type, Alloc>,
int> = 0>
265 constexpr mdarray (
const mapping_type& m,
const value_type& v,
const Alloc& a)
266 : container_(m.required_span_size(), v, a)
271 template <
class Alloc,
272 std::enable_if_t<std::is_constructible_v<container_type, container_type, Alloc>,
int> = 0>
273 constexpr mdarray (
const extents_type& e,
const container_type& c,
const Alloc& a)
279 template <
class Alloc,
280 std::enable_if_t<std::is_constructible_v<container_type, container_type, Alloc>,
int> = 0>
281 constexpr mdarray (
const extents_type& e, container_type&& c,
const Alloc& a)
282 : container_(
std::move(c), a)
287 template <
class Alloc,
288 std::enable_if_t<std::is_constructible_v<container_type, container_type, Alloc>,
int> = 0>
289 constexpr mdarray (
const mapping_type& m,
const container_type& c,
const Alloc& a)
295 template <
class Alloc,
296 std::enable_if_t<std::is_constructible_v<container_type, container_type, Alloc>,
int> = 0>
297 constexpr mdarray (
const mapping_type& m, container_type&& c,
const Alloc& a)
298 : container_(
std::move(c), a)
303 template <
class V,
class E,
class L,
class C,
class Alloc,
304 std::enable_if_t<std::is_constructible_v<container_type, C, Alloc>,
int> = 0>
305 #if __cpp_conditional_explicit >= 201806L
307 !std::is_convertible_v<const typename L::template mapping<E>&, mapping_type> ||
308 !std::is_convertible_v<const C&, container_type>)
311 : container_(other.container_, a)
312 , mapping_(other.mapping_)
316 template <
class V,
class E,
class L,
class A,
class Alloc,
317 class C = container_type,
318 class Al =
typename C::allocator_type,
319 std::enable_if_t<std::is_constructible_v<C, std::size_t, Alloc>,
int> = 0>
320 #if __cpp_conditional_explicit >= 201806L
322 !std::is_convertible_v<const typename L::template mapping<E>&, mapping_type> ||
323 !std::is_convertible_v<typename A::reference, value_type> ||
324 !std::is_convertible_v<Alloc, Al>)
327 : container_(other.
size(), a)
328 , mapping_(other.mapping_)
330 init_from_mdspan(other);
337 template <
class V,
class E,
class L,
class A,
class...
Indices>
340 constexpr rank_type pos =
sizeof...(Indices);
341 if constexpr(pos <
rank()) {
342 for (
typename E::index_type i = 0; i < other.
extent(pos); ++i)
343 init_from_mdspan(other,ii...,i);
345 using I = std::array<
typename E::index_type,E::rank()>;
346 container_[mapping_(index_type(ii)...)] = other[I{ii...}];
362 std::enable_if_t<(
sizeof...(Indices) == extents_type::rank()),
int> = 0,
363 std::enable_if_t<(... && std::is_convertible_v<Indices,index_type>),
int> = 0>
366 return container_[mapping_(index_type(std::move(indices))...)];
374 std::enable_if_t<(
sizeof...(Indices) == extents_type::rank()),
int> = 0,
375 std::enable_if_t<(... && std::is_convertible_v<Indices,index_type>),
int> = 0>
378 return container_[mapping_(index_type(std::move(indices))...)];
382#if __cpp_multidimensional_subscript >= 202110L
386 std::enable_if_t<(
sizeof...(Indices) == extents_type::rank()),
int> = 0,
387 std::enable_if_t<(... && std::is_convertible_v<Indices,index_type>),
int> = 0>
390 return container_[mapping_(index_type(std::move(indices))...)];
395 std::enable_if_t<(
sizeof...(Indices) == extents_type::rank()),
int> = 0,
396 std::enable_if_t<(... && std::is_convertible_v<Indices,index_type>),
int> = 0>
399 return container_[mapping_(index_type(std::move(indices))...)];
406 template <
class Index,
class E = extents_type,
407 std::enable_if_t<std::is_convertible_v<Index,index_type>,
int> = 0,
408 std::enable_if_t<(E::rank() == 1),
int> = 0>
409 constexpr reference
operator[] (Index index)
411 return container_[mapping_(index_type(std::move(index)))];
416 template <
class Index,
class E = extents_type,
417 std::enable_if_t<std::is_convertible_v<Index,index_type>,
int> = 0,
418 std::enable_if_t<(E::rank() == 1),
int> = 0>
419 constexpr const_reference
operator[] (Index index)
const
421 return container_[mapping_(index_type(std::move(index)))];
428 template <
class Index,
429 std::enable_if_t<std::is_convertible_v<const Index&, index_type>,
int> = 0>
433 return container_[mapping_(index_type(indices[ii])...)]; },
434 std::make_index_sequence<extents_type::rank()>{});
438 template <
class Index,
439 std::enable_if_t<std::is_convertible_v<const Index&, index_type>,
int> = 0>
443 return container_[mapping_(index_type(indices[ii])...)]; },
444 std::make_index_sequence<extents_type::rank()>{});
448 template <
class Index,
449 std::enable_if_t<std::is_convertible_v<const Index&, index_type>,
int> = 0>
450 constexpr reference
operator[] (
const std::array<Index,extents_type::rank()>& indices)
452 return std::apply([&](
auto... ii) -> reference {
453 return container_[mapping_(index_type(ii)...)]; }, indices);
457 template <
class Index,
458 std::enable_if_t<std::is_convertible_v<const Index&, index_type>,
int> = 0>
459 constexpr const_reference
operator[] (
const std::array<Index,extents_type::rank()>& indices)
const
461 return std::apply([&](
auto... ii) -> const_reference {
462 return container_[mapping_(index_type(ii)...)]; }, indices);
469 constexpr const extents_type&
extents () const noexcept {
return mapping_.extents(); }
472 constexpr const mapping_type&
mapping () const noexcept {
return mapping_; }
475 constexpr const container_type&
container () const noexcept {
return container_; }
490 static constexpr rank_type
rank () noexcept {
return extents_type::rank(); }
493 static constexpr rank_type
rank_dynamic () noexcept {
return extents_type::rank_dynamic(); }
496 static constexpr std::size_t
static_extent (rank_type r)
noexcept {
return extents_type::static_extent(r); }
499 constexpr index_type
extent (rank_type r)
const noexcept {
return extents().extent(r); }
502 constexpr size_type
size () const noexcept
505 for (rank_type r = 0; r <
rank(); ++r)
514 [[nodiscard]]
constexpr bool empty () const noexcept {
return size() == 0; }
517 constexpr index_type
stride (rank_type r)
const {
return mapping().stride(r); };
522 static constexpr bool is_always_unique () noexcept {
return mapping_type::is_always_unique(); }
523 static constexpr bool is_always_exhaustive () noexcept {
return mapping_type::is_always_exhaustive(); }
524 static constexpr bool is_always_strided () noexcept {
return mapping_type::is_always_strided(); }
526 constexpr bool is_unique () const noexcept {
return mapping_.is_unique(); }
527 constexpr bool is_exhaustive () const noexcept {
return mapping_.is_exhaustive(); }
528 constexpr bool is_strided () const noexcept {
return mapping_.is_strided(); }
546 swap(x.container_, y.container_);
547 swap(x.mapping_, y.mapping_);
554 friend constexpr bool operator== (
const mdarray& lhs,
const mdarray& rhs)
noexcept
556 return lhs.mapping() == rhs.mapping() && lhs.container() == rhs.container();
565 template <
class V,
class E,
class L,
class A,
566 std::enable_if_t<std::is_assignable_v<mdspan<V,E,L,A>, mdspan_type>,
int> = 0>
573 template <
class V,
class E,
class L,
class A,
574 std::enable_if_t<std::is_assignable_v<mdspan<V,E,L,A>, const_mdspan_type>,
int> = 0>
581 template <
class AccessorPolicy = Std::default_accessor<element_type>,
583 std::is_assignable_v<mdspan_type, mdspan<element_type,extents_type,layout_type,AccessorPolicy>>,
int> = 0>
591 template <
class AccessorPolicy = Std::default_accessor<const element_type>,
593 std::is_assignable_v<const_mdspan_type, mdspan<const element_type,extents_type,layout_type,AccessorPolicy>>,
int> = 0>
594 constexpr mdspan<const element_type,extents_type,layout_type,AccessorPolicy>
595 to_mdspan (
const AccessorPolicy& a = AccessorPolicy{})
const
601 container_type container_;
602 DUNE_NO_UNIQUE_ADDRESS mapping_type mapping_;
609template <
class IndexType, std::size_t... exts,
class Container>
610mdarray (
const Std::extents<IndexType, exts...>&,
const Container&)
611 -> mdarray<
typename Container::value_type, Std::extents<IndexType, exts...>, layout_right, Container>;
613template <
class Mapping,
class Container>
614mdarray (
const Mapping&,
const Container&)
615 -> mdarray<typename Container::value_type, typename Mapping::extents_type, typename Mapping::layout_type, Container>;
617template <
class IndexType, std::size_t... exts,
class Container>
618mdarray (
const Std::extents<IndexType, exts...>&, Container&&)
619 -> mdarray<
typename Container::value_type, Std::extents<IndexType, exts...>, layout_right, Container>;
621template <
class Mapping,
class Container>
622mdarray (
const Mapping&, Container&&)
623 -> mdarray<typename Container::value_type, typename Mapping::extents_type, typename Mapping::layout_type, Container>;
625template <
class Element,
class Extents,
class Layout,
class Accessor>
626mdarray (
const mdspan<Element, Extents, Layout, Accessor>&)
627 -> mdarray<std::remove_cv_t<Element>, Extents, Layout>;
629template <
class IndexType, std::size_t... exts,
class Container,
class Alloc>
630mdarray (
const Std::extents<IndexType, exts...>&,
const Container&,
const Alloc&)
631 -> mdarray<
typename Container::value_type, Std::extents<IndexType, exts...>, layout_right, Container>;
633template <
class Mapping,
class Container,
class Alloc>
634mdarray (
const Mapping&,
const Container&,
const Alloc&)
635 -> mdarray<typename Container::value_type, typename Mapping::extents_type, typename Mapping::layout_type, Container>;
637template <
class IndexType, std::size_t... exts,
class Container,
class Alloc>
638mdarray (
const Std::extents<IndexType, exts...>&, Container&&,
const Alloc&)
639 -> mdarray<
typename Container::value_type, Std::extents<IndexType, exts...>, layout_right, Container>;
641template <
class Mapping,
class Container,
class Alloc>
642mdarray (
const Mapping&, Container&&,
const Alloc&)
643 -> mdarray<typename Container::value_type, typename Mapping::extents_type, typename Mapping::layout_type, Container>;
645template <
class Element,
class Extents,
class Layout,
class Accessor,
class Alloc>
646mdarray (
const mdspan<Element, Extents, Layout, Accessor>&,
const Alloc&)
647 -> mdarray<std::remove_cv_t<Element>, Extents, Layout>;
655template <
class Element,
class Extents,
class Layout,
class Container>
656mdspan (mdarray<Element, Extents, Layout, Container>) -> mdspan<
657 typename decltype(std::declval<mdarray<Element, Extents, Layout, Container>>().to_mdspan())::element_type,
658 typename decltype(std::declval<mdarray<Element, Extents, Layout, Container>>().to_mdspan())::extents_type,
659 typename decltype(std::declval<mdarray<Element, Extents, Layout, Container>>().to_mdspan())::layout_type,
660 typename decltype(std::declval<mdarray<Element, Extents, Layout, Container>>().to_mdspan())::accessor_type>;
An owning multi-dimensional array analog of mdspan.
Definition: mdarray.hh:70
constexpr mdarray(const mapping_type &m, const container_type &c, const Alloc &a)
Construct from layout mapping, container and allocator.
Definition: mdarray.hh:289
constexpr mdarray(const mapping_type &m, container_type &&c)
Construct from layout mapping and the storage container.
Definition: mdarray.hh:195
constexpr mdarray(const E &e, const container_type &c)
Construct from extents and the storage container.
Definition: mdarray.hh:175
constexpr mdspan< const element_type, extents_type, layout_type, AccessorPolicy > to_mdspan(const AccessorPolicy &a=AccessorPolicy{}) const
Conversion function to mdspan.
Definition: mdarray.hh:595
constexpr index_type stride(rank_type r) const
The stride along the specified dimension.
Definition: mdarray.hh:517
constexpr index_type extent(rank_type r) const noexcept
Number of elements in the r'th dimension of the tensor.
Definition: mdarray.hh:499
constexpr mdarray(const extents_type &e, const Alloc &a)
Construct from the extents of the array and allocator.
Definition: mdarray.hh:244
static constexpr std::size_t static_extent(rank_type r) noexcept
Number of elements in the r'th dimension of the tensor.
Definition: mdarray.hh:496
constexpr mdarray(const mdspan< OtherElementType, OtherExtents, OtherLayoutPolicy, Accessor > &other)
Converting constructor from mdspan.
Definition: mdarray.hh:230
constexpr const_pointer container_data() const noexcept
Direct access to the underlying const data in the container.
Definition: mdarray.hh:538
constexpr mdarray(const extents_type &e, const value_type &v)
Construct from extents and initial value.
Definition: mdarray.hh:156
constexpr mdarray(const mapping_type &m, const Alloc &a)
Construct from the layout mapping of the array and allocator.
Definition: mdarray.hh:251
constexpr pointer container_data() noexcept
Direct access to the underlying data in the container.
Definition: mdarray.hh:535
constexpr reference operator[](Index index)
Access specified element at position [i0] For a rank one mdarray, the operator[i] is added to support...
Definition: mdarray.hh:409
constexpr const extents_type & extents() const noexcept
Number of elements in all dimensions of the array,.
Definition: mdarray.hh:469
constexpr mdarray(const mapping_type &m, const container_type &c)
Construct from layout mapping and the storage container.
Definition: mdarray.hh:189
constexpr mdarray(const mapping_type &m, container_type &&c, const Alloc &a)
Construct from layout mapping, container and allocator.
Definition: mdarray.hh:297
constexpr mdarray(const E &e, container_type &&c)
Construct from extents and the storage container.
Definition: mdarray.hh:183
constexpr const container_type & container() const noexcept
The underlying storage container.
Definition: mdarray.hh:475
constexpr std::size_t container_size() const
Size of the underlying container.
Definition: mdarray.hh:511
static constexpr rank_type rank() noexcept
Number of dimensions of the array.
Definition: mdarray.hh:490
constexpr bool empty() const noexcept
Check whether the index space is empty.
Definition: mdarray.hh:514
constexpr mdarray(const extents_type &e, container_type &&c, const Alloc &a)
Construct from extents, container and allocator.
Definition: mdarray.hh:281
constexpr size_type size() const noexcept
Size of the multi-dimensional index space.
Definition: mdarray.hh:502
constexpr const mapping_type & mapping() const noexcept
Index mapping of a layout policy.
Definition: mdarray.hh:472
constexpr mdarray(const mapping_type &m, const value_type &v, const Alloc &a)
Construct from layout mapping, initial value and allocator.
Definition: mdarray.hh:265
constexpr mdarray(const extents_type &e, const value_type &v, const Alloc &a)
Construct from extents, initial value and allocator.
Definition: mdarray.hh:258
constexpr mdspan< element_type, extents_type, layout_type, AccessorPolicy > to_mdspan(const AccessorPolicy &a=AccessorPolicy{})
Conversion function to mdspan.
Definition: mdarray.hh:585
constexpr container_type && extract_container() &&noexcept
Move the container out of the mdarray.
Definition: mdarray.hh:483
constexpr mdarray(const extents_type &e, const container_type &c, const Alloc &a)
Construct from extents, container and allocator.
Definition: mdarray.hh:273
static constexpr rank_type rank_dynamic() noexcept
Number of dimension with dynamic size.
Definition: mdarray.hh:493
constexpr reference operator()(Indices... indices)
Access element at position (i0,i1,...)
Definition: mdarray.hh:364
constexpr mdarray(const extents_type &e)
Construct from the extents of the array.
Definition: mdarray.hh:139
constexpr mdarray(IndexTypes... exts)
Construct from the dynamic extents.
Definition: mdarray.hh:134
A multi-dimensional non-owning array view.
Definition: mdspan.hh:65
constexpr index_type extent(rank_type r) const noexcept
Number of elements in the r'th dimension of the tensor.
Definition: mdspan.hh:276
constexpr size_type size() const noexcept
The number of elements accessible by this multi-dimensional span.
Definition: mdspan.hh:279
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
EnableIfInterOperable< T1, T2, bool >::type operator==(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for equality.
Definition: iteratorfacades.hh:238
Namespace with predefined compile time indices for the range [0,19].
Definition: indices.hh:50
Namespace for features backported from new C++ standards.
Definition: default_accessor.hh:10
constexpr auto to_address(T &&p) noexcept
Obtain the address represented by p without forming a reference to the object pointed to by p.
Definition: memory.hh:47
Utilities for reduction like operations on ranges.
Get the 'const' version of a reference to a mutable object.
Definition: genericiterator.hh:87