dune-common 2.12-git
Loading...
Searching...
No Matches
layout_right_padded.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_RIGHT_PADDED_HH
6#define DUNE_COMMON_STD_LAYOUT_RIGHT_PADDED_HH
7
8#include <cassert>
9#include <span>
10#include <type_traits>
11
17
18namespace Dune::Std {
19namespace Impl {
20
21template <class Layout>
22struct IsLayoutRightPadded : std::false_type {};
23
24template <std::size_t PaddingValue>
25struct IsLayoutRightPadded<layout_right_padded<PaddingValue>> : std::true_type {};
26
27template <class Layout>
28inline constexpr bool is_layout_right_padded_v = IsLayoutRightPadded<Layout>::value;
29
30} // end namespace Impl
31
49template <std::size_t PaddingValue>
50template <class Extents>
51class layout_right_padded<PaddingValue>::mapping
52{
53public:
54 using extents_type = Extents;
55 using index_type = typename extents_type::index_type;
56 using size_type = typename extents_type::size_type;
57 using rank_type = typename extents_type::rank_type;
59
60 static constexpr std::size_t padding_value = PaddingValue;
61
62 constexpr mapping () noexcept = default;
63 constexpr mapping (const mapping&) noexcept = default;
64
65 constexpr mapping (const extents_type& e) noexcept
66 : extents_(e)
67 , stride_before_last_(default_stride_before_last(e))
68 {}
69
70 template <class OtherIndexType,
73 constexpr mapping (const extents_type& e, OtherIndexType padding) noexcept
74 : extents_(e)
75 , stride_before_last_(index_type(padding))
76 {
77 assert(Extents::rank() <= 1 || index_type(padding) >= e.extent(Extents::rank()-1));
78 if constexpr(PaddingValue != std::dynamic_extent)
79 assert(index_type(PaddingValue) == index_type(padding));
80 }
81
82 template <class OtherExtents,
84 constexpr mapping (const layout_right::mapping<OtherExtents>& m) noexcept
85 : mapping(extents_type(m.extents()))
86 {}
87
88 template <class OtherExtents, class E = extents_type,
89 std::enable_if_t<(E::rank() <= 1), int> = 0,
90 std::enable_if_t<std::is_constructible_v<extents_type, OtherExtents>, int> = 0>
91 constexpr mapping (const layout_left::mapping<OtherExtents>& m) noexcept
93 {}
94
95 template <class OtherExtents,
97 constexpr mapping (const layout_stride::mapping<OtherExtents>& m) noexcept
98 : extents_(m.extents())
99 , stride_before_last_(Extents::rank() > 1 ? m.stride(Extents::rank()-2) : index_type(0))
100 {
101#ifndef NDEBUG
102 if constexpr(Extents::rank() > 0)
103 assert(m.stride(Extents::rank()-1) == 1);
104 if constexpr(Extents::rank() > 1)
105 for (rank_type r = 0; r + 2 < Extents::rank(); ++r)
106 assert(m.stride(r) == stride_before_last_ * rev_product(r));
107#endif
108 }
109
110 template <class OtherMapping,
113 constexpr mapping (const OtherMapping& m) noexcept
114 : extents_(m.extents())
115 , stride_before_last_(Extents::rank() > 1 ? m.stride(Extents::rank()-2) : index_type(0))
116 {}
117
118 constexpr mapping& operator= (const mapping&) noexcept = default;
119
120 constexpr const extents_type& extents () const noexcept { return extents_; }
121
122 constexpr index_type required_span_size () const noexcept
123 {
124 if constexpr(Extents::rank() == 0)
125 return 1;
126 else {
127 if (product() == 0)
128 return 0;
129 index_type result = 1;
130 for (rank_type r = 0; r < Extents::rank(); ++r)
131 result += (extents_.extent(r)-1) * stride(r);
132 return result;
133 }
134 }
135
136 template <class... Indices,
137 std::enable_if_t<(sizeof...(Indices) == Extents::rank()), int> = 0,
138 std::enable_if_t<(... && std::is_convertible_v<Indices,index_type>), int> = 0>
139 constexpr index_type operator() (Indices... indices) const noexcept
140 {
141 const index_type ii[] = {index_type(indices)...};
142 index_type result = 0;
143 for (rank_type r = 0; r < Extents::rank(); ++r)
144 result += ii[r] * stride(r);
145 return result;
146 }
147
148 constexpr index_type operator() () const noexcept { return 0; }
149
150 static constexpr bool is_always_unique () noexcept { return true; }
151 static constexpr bool is_always_exhaustive () noexcept { return PaddingValue == std::dynamic_extent; }
152 static constexpr bool is_always_strided () noexcept { return true; }
153
154 constexpr bool is_unique () const noexcept { return true; }
155 constexpr bool is_strided () const noexcept { return true; }
156 constexpr bool is_exhaustive () const noexcept
157 {
158 return Extents::rank() <= 1 || stride_before_last_ == extents_.extent(Extents::rank()-1);
159 }
160
161 template <class E = extents_type,
162 std::enable_if_t<(E::rank() > 0), int> = 0>
163 constexpr index_type stride (rank_type r) const noexcept
164 {
165 assert(r < Extents::rank());
166 if (r + 1 == Extents::rank())
167 return 1;
168 if (r + 2 == Extents::rank())
169 return stride_before_last_;
170 return stride_before_last_ * rev_product(r);
171 }
172
173 template <class OtherMapping,
174 std::enable_if_t<(OtherMapping::extents_type::rank() == Extents::rank()), int> = 0,
175 std::enable_if_t<(OtherMapping::is_always_strided()), int> = 0>
176 friend constexpr bool operator== (const mapping& a, const OtherMapping& b) noexcept
177 {
178 if (a.extents_ != b.extents())
179 return false;
180 for (rank_type r = 0; r < Extents::rank(); ++r)
181 if (a.stride(r) != b.stride(r))
182 return false;
183 return true;
184 }
185
186private:
187 static constexpr index_type padded_stride (index_type padding, index_type extent) noexcept
188 {
189 assert(padding >= extent);
190 return padding;
191 }
192
193 static constexpr index_type default_stride_before_last (const extents_type& e) noexcept
194 {
195 if constexpr(Extents::rank() <= 1)
196 return 0;
197 else if constexpr(PaddingValue == std::dynamic_extent)
198 return e.extent(Extents::rank()-1);
199 else
200 return padded_stride(index_type(PaddingValue), e.extent(Extents::rank()-1));
201 }
202
203 constexpr index_type rev_product (rank_type r) const noexcept
204 {
205 index_type prod = 1;
206 for (rank_type k = r + 1; k + 1 < Extents::rank(); ++k)
207 prod *= extents_.extent(k);
208 return prod;
209 }
210
211 constexpr size_type product () const noexcept
212 {
213 size_type prod = 1;
214 for (rank_type r = 0; r < Extents::rank(); ++r)
215 prod *= extents_.extent(r);
216 return prod;
217 }
218
219private:
220 DUNE_NO_UNIQUE_ADDRESS extents_type extents_;
221 index_type stride_before_last_ = 0;
222};
223
224} // end namespace Dune::Std
225
226#endif // DUNE_COMMON_STD_LAYOUT_RIGHT_PADDED_HH
#define DUNE_NO_UNIQUE_ADDRESS
Definition no_unique_address.hh:24
Namespace for features backported from new C++ standards.
Definition algorithm.hh:19
A layout mapping where the leftmost extent has stride 1.
Definition layout_left.hh:20
constexpr index_type stride(rank_type i) const noexcept
The stride is the product of the extents E(0)*E(1)*...*E(i-1)
Definition layout_left.hh:122
constexpr const extents_type & extents() const noexcept
Definition layout_left.hh:86
A layout mapping where the rightmost extent has stride 1.
Definition layout_right.hh:20
A layout mapping where the strides are user-defined.
Definition layout_stride.hh:21
A layout mapping where the rightmost extent has stride 1 and the next-to-last stride may be padded.
Definition fwd_layouts.hh:66
A right layout mapping with optional padding of the next-to-last stride.
Definition layout_right_padded.hh:52
constexpr mapping(const layout_stride::mapping< OtherExtents > &m) noexcept
Definition layout_right_padded.hh:97
Extents extents_type
Definition layout_right_padded.hh:54
constexpr mapping(const OtherMapping &m) noexcept
Definition layout_right_padded.hh:113
constexpr index_type required_span_size() const noexcept
Definition layout_right_padded.hh:122
static constexpr bool is_always_exhaustive() noexcept
Definition layout_right_padded.hh:151
static constexpr bool is_always_unique() noexcept
Definition layout_right_padded.hh:150
typename extents_type::rank_type rank_type
Definition layout_right_padded.hh:57
constexpr bool is_strided() const noexcept
Definition layout_right_padded.hh:155
constexpr bool is_unique() const noexcept
Definition layout_right_padded.hh:154
constexpr mapping(const layout_right::mapping< OtherExtents > &m) noexcept
Definition layout_right_padded.hh:84
constexpr bool is_exhaustive() const noexcept
Definition layout_right_padded.hh:156
typename extents_type::size_type size_type
Definition layout_right_padded.hh:56
typename extents_type::index_type index_type
Definition layout_right_padded.hh:55
static constexpr bool is_always_strided() noexcept
Definition layout_right_padded.hh:152
constexpr mapping(const extents_type &e, OtherIndexType padding) noexcept
Definition layout_right_padded.hh:73
constexpr const extents_type & extents() const noexcept
Definition layout_right_padded.hh:120
constexpr index_type stride(rank_type r) const noexcept
Definition layout_right_padded.hh:163
constexpr mapping() noexcept=default