dune-common  2.11
layout_stride.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 // SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5 #ifndef DUNE_COMMON_STD_LAYOUT_STRIDE_HH
6 #define DUNE_COMMON_STD_LAYOUT_STRIDE_HH
7 
8 #include <array>
9 #include <span>
10 #include <type_traits>
11 
12 #include <dune/common/indices.hh>
15 
16 namespace Dune::Std {
17 
19 template <class Extents>
20 class layout_stride::mapping
21 {
22  template <class> friend class mapping;
23  static constexpr typename Extents::rank_type rank_ = Extents::rank();
24 
25 public:
26  using extents_type = Extents;
27  using index_type = typename extents_type::index_type;
28  using size_type = typename extents_type::size_type;
29  using rank_type = typename extents_type::rank_type;
31 
32 private:
33  using strides_type = std::array<index_type,rank_>;
34 
35 public:
36 
38  constexpr mapping () noexcept
40  {}
41 
43  constexpr mapping (const mapping&) noexcept = default;
44 
46  template <class OtherIndexType,
47  std::enable_if_t<std::is_convertible_v<const OtherIndexType&, index_type>, int> = 0,
48  std::enable_if_t<std::is_nothrow_constructible_v<index_type, const OtherIndexType&>, int> = 0>
49  constexpr mapping (const extents_type& e, const std::array<OtherIndexType,rank_>& s) noexcept
50  : extents_(e)
51  , strides_{}
52  {
53  for (rank_type r = 0; r < rank_; ++r)
54  strides_[r] = s[r];
55  }
56 
58  template <class OtherIndexType,
59  std::enable_if_t<std::is_convertible_v<const OtherIndexType&, index_type>, int> = 0,
60  std::enable_if_t<std::is_nothrow_constructible_v<index_type, const OtherIndexType&>, int> = 0>
61  constexpr mapping (const extents_type& e, const std::span<OtherIndexType,rank_>& s) noexcept
62  : extents_(e)
63  , strides_{}
64  {
65  for (rank_type r = 0; r < rank_; ++r)
66  strides_[r] = s[r];
67  }
68 
70  template <class M,
71  std::enable_if_t<(M::extents_type::rank() == extents_type::rank()), int> = 0,
72  std::enable_if_t<(M::is_always_unique()), int> = 0,
73  std::enable_if_t<(M::is_always_strided()), int> = 0,
74  decltype(std::declval<M>().extents(), bool{}) = true,
75  decltype(std::declval<M>().stride(std::declval<rank_type>()), bool{}) = true>
76  constexpr mapping (const M& m) noexcept
77  : extents_(m.extents())
78  , strides_{}
79  {
80  for (rank_type r = 0; r < rank_; ++r)
81  strides_[r] = m.stride(r);
82  }
83 
85  constexpr mapping& operator= (const mapping&) noexcept = default;
86 
87  constexpr const extents_type& extents () const noexcept { return extents_; }
88 
90  constexpr index_type required_span_size () const noexcept
91  {
92  return size(extents_,strides_);
93  }
94 
96  template <class... Indices,
97  std::enable_if_t<(sizeof...(Indices) == rank_), int> = 0,
98  std::enable_if_t<(std::is_convertible_v<Indices, index_type> && ...), int> = 0,
99  std::enable_if_t<(std::is_nothrow_constructible_v<index_type, Indices> && ...), int> = 0>
100  constexpr index_type operator() (Indices... ii) const noexcept
101  {
102  return unpackIntegerSequence([&](auto... r) {
103  return ((static_cast<index_type>(ii)*strides_[r]) + ... + 0); },
104  std::make_index_sequence<rank_>{});
105  }
106 
108  constexpr index_type operator() () const noexcept
109  {
110  return 0;
111  }
112 
113  static constexpr bool is_always_unique () noexcept { return true; }
114  static constexpr bool is_always_exhaustive () noexcept { return false; }
115  static constexpr bool is_always_strided () noexcept { return true; }
116 
117  static constexpr bool is_unique () noexcept { return true; }
118  static constexpr bool is_strided () noexcept { return true; }
119 
120  constexpr bool is_exhaustive () const noexcept
121  {
122  // Actually this could be improved. A strided layout can still be exhaustive.
123  // This test is more complicated to implement, though. See §24.7.3.4.7.4 line (5.2)
124  // in the C++ standard document N4971
125  return extents_type::rank() == 0 || (required_span_size() > 0 && required_span_size() == extents().product());
126  }
127 
129  constexpr const strides_type& strides () const noexcept
130  {
131  return strides_;
132  }
133 
135  template <class E = extents_type,
136  std::enable_if_t<(E::rank() > 0), int> = 0>
137  constexpr index_type stride (rank_type i) const noexcept
138  {
139  return strides_[i];
140  }
141 
142  template <class OtherMapping,
143  std::enable_if_t<(OtherMapping::extents_type::rank() == extents_type::rank()), int> = 0,
144  std::enable_if_t<(OtherMapping::is_always_strided()), int> = 0>
145  friend constexpr bool operator== (const mapping& a, const OtherMapping& b) noexcept
146  {
147  if (offset(b))
148  return false;
149  if constexpr(extents_type::rank() == 0)
150  return true;
151  return a.extents_ == b.extents_ && a.strides_ == b.strides_;
152  }
153 
154 private:
155  template <class E, class S>
156  static constexpr index_type size (const E& extents, const S& strides) noexcept
157  {
158  if constexpr (E::rank() == 0)
159  return 1;
160  else {
161  if (extents.product() == 0)
162  return 0;
163  else {
164  index_type result = 1;
165  for (rank_type r = 0; r < E::rank(); ++r)
166  result += (extents.extent(r)-1) * strides[r];
167  return result;
168  }
169  }
170  }
171 
172  template <class M>
173  static constexpr size_type offset (const M& m) noexcept
174  {
175  if constexpr (M::extents_type::rank() == 0)
176  return m();
177  else {
178  if (m.required_span_size() == 0)
179  return 0;
180  else {
181  return unpackIntegerSequence([&](auto... r) {
182  return m((r,0)...); }, // map the index tuple (0,0...)
183  std::make_index_sequence<M::extents_type::rank()>{});
184  }
185  }
186  }
187 
188 private:
190  strides_type strides_;
191 };
192 
193 } // end namespace Dune::Std
194 
195 #endif // DUNE_COMMON_STD_LAYOUT_STRIDE_HH
A layout mapping where the strides are user-defined.
Definition: fwd_layouts.hh:42
Namespace for features backported from new C++ standards.
Definition: algorithm.hh:19
static constexpr bool is_always_exhaustive() noexcept
Definition: layout_stride.hh:114
typename extents_type::index_type index_type
Definition: layout_stride.hh:27
constexpr mapping() noexcept
The default construction initializes the strides from layout_right.
Definition: layout_stride.hh:38
constexpr mapping & operator=(const mapping &) noexcept=default
Copy-assignment for the mapping.
constexpr index_type extent(rank_type r) const noexcept
Return the extent of dimension i
Definition: extents.hh:101
constexpr bool is_exhaustive() const noexcept
Definition: layout_stride.hh:120
decltype(auto) constexpr unpackIntegerSequence(F &&f, [[maybe_unused]] std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition: indices.hh:124
typename extents_type::rank_type rank_type
Definition: layout_stride.hh:29
constexpr index_type operator()() const noexcept
The default offset for rank-0 tensors is 0.
Definition: layout_stride.hh:108
#define DUNE_NO_UNIQUE_ADDRESS
Definition: no_unique_address.hh:24
Extents extents_type
Definition: layout_stride.hh:26
constexpr index_type stride(rank_type i) const noexcept
Get the single stride i
Definition: layout_stride.hh:137
typename extents_type::size_type size_type
Definition: layout_stride.hh:28
constexpr const extents_type & extents() const noexcept
Definition: layout_stride.hh:87
Multidimensional index space with dynamic and static extents.This class template represents a multidi...
Definition: extents.hh:54
I i
Definition: hybridmultiindex.hh:328
static constexpr bool is_strided() noexcept
Definition: layout_stride.hh:118
constexpr mapping(const extents_type &e, const std::array< OtherIndexType, rank_ > &s) noexcept
Construct the mapping from given extents and strides.
Definition: layout_stride.hh:49
A layout where the rightmost extent has stride 1, and strides increase right-to-left as the product o...
Definition: fwd_layouts.hh:29
static constexpr bool is_always_strided() noexcept
Definition: layout_stride.hh:115
A layout mapping where the strides are user-defined.
Definition: fwd_layouts.hh:39
constexpr const strides_type & strides() const noexcept
Get the array of all strides.
Definition: layout_stride.hh:129
static constexpr bool is_always_unique() noexcept
Definition: layout_stride.hh:113
friend constexpr bool operator==(const mapping &a, const OtherMapping &b) noexcept
Definition: layout_stride.hh:145
static constexpr bool is_unique() noexcept
Definition: layout_stride.hh:117
constexpr mapping(const extents_type &e, const std::span< OtherIndexType, rank_ > &s) noexcept
Construct the mapping from given extents and strides.
Definition: layout_stride.hh:61
constexpr index_type required_span_size() const noexcept
Return the sum 1 + (E(0)-1)*S(0) + (E(1)-1)*S(1) + ...
Definition: layout_stride.hh:90