DDC 0.0.0

a discrete domain computation library

discrete_element.hpp
1 // SPDX-License-Identifier: MIT
2 
3 #pragma once
4 
5 #include <array>
6 #include <cstddef>
7 #include <ostream>
8 #include <utility>
9 
10 #include "ddc/detail/type_seq.hpp"
11 #include "ddc/discrete_vector.hpp"
12 
13 namespace ddc {
14 
15 template <class...>
16 class DiscreteElement;
17 
18 template <class T>
19 struct IsDiscreteElement : std::false_type
20 {
21 };
22 
23 template <class... Tags>
24 struct IsDiscreteElement<DiscreteElement<Tags...>> : std::true_type
25 {
26 };
27 
28 template <class T>
30 
31 
34 using DiscreteElementType = std::size_t;
35 
36 template <class Tag>
37 inline constexpr DiscreteElementType const& uid(DiscreteElement<Tag> const& tuple) noexcept
38 {
39  return tuple.uid();
40 }
41 
42 template <class Tag>
43 inline constexpr DiscreteElementType& uid(DiscreteElement<Tag>& tuple) noexcept
44 {
45  return tuple.uid();
46 }
47 
48 template <class QueryTag, class... Tags>
49 inline constexpr DiscreteElementType const& uid(DiscreteElement<Tags...> const& tuple) noexcept
50 {
51  return tuple.template uid<QueryTag>();
52 }
53 
54 template <class QueryTag, class... Tags>
55 inline constexpr DiscreteElementType& uid(DiscreteElement<Tags...>& tuple) noexcept
56 {
57  return tuple.template uid<QueryTag>();
58 }
59 
60 template <class QueryTag, class... Tags>
61 inline constexpr DiscreteElementType const& uid_or(
62  DiscreteElement<Tags...> const& tuple,
63  DiscreteElementType const& default_value) noexcept
64 {
65  return tuple.template uid_or<QueryTag>(default_value);
66 }
67 
68 template <class... QueryTags, class... Tags>
69 inline constexpr DiscreteElement<QueryTags...> select(DiscreteElement<Tags...> const& arr) noexcept
70 {
71  return DiscreteElement<QueryTags...>(arr);
72 }
73 
74 template <class... QueryTags, class... Tags>
75 inline constexpr DiscreteElement<QueryTags...> select(DiscreteElement<Tags...>&& arr) noexcept
76 {
77  return DiscreteElement<QueryTags...>(std::move(arr));
78 }
79 
80 template <class QueryTag, class HeadTag, class... TailTags>
82  DiscreteElement<HeadTag> const& head,
83  DiscreteElement<TailTags> const&... tags)
84 {
85  DDC_IF_NVCC_THEN_PUSH_AND_SUPPRESS(implicit_return_from_non_void_function)
86  static_assert(
87  !type_seq_contains_v<ddc_detail::TypeSeq<HeadTag>, ddc_detail::TypeSeq<TailTags...>>,
88  "ERROR: tag redundant");
89  if constexpr (std::is_same_v<QueryTag, HeadTag>) {
90  return head;
91  } else {
92  static_assert(sizeof...(TailTags) > 0, "ERROR: tag not found");
93  return take<QueryTag>(tags...);
94  }
95  DDC_IF_NVCC_THEN_POP
96 }
97 
98 namespace ddc_detail {
99 
101 template <class... Tags>
102 constexpr inline std::array<DiscreteElementType, sizeof...(Tags)>& array(
103  DiscreteElement<Tags...>& v) noexcept
104 {
105  return v.m_values;
106 }
107 
109 template <class... Tags>
110 constexpr inline std::array<DiscreteElementType, sizeof...(Tags)> const& array(
111  DiscreteElement<Tags...> const& v) noexcept
112 {
113  return v.m_values;
114 }
115 
116 } // namespace ddc_detail
117 
122 template <class... Tags>
124 {
125  using tags_seq = ddc_detail::TypeSeq<Tags...>;
126 
127  friend constexpr std::array<DiscreteElementType, sizeof...(Tags)>& ddc_detail::array<Tags...>(
128  DiscreteElement<Tags...>& v) noexcept;
129 
130  friend constexpr std::array<DiscreteElementType, sizeof...(Tags)> const& ddc_detail::array<
131  Tags...>(DiscreteElement<Tags...> const& v) noexcept;
132 
133 private:
134  std::array<DiscreteElementType, sizeof...(Tags)> m_values;
135 
136 public:
138 
139  static constexpr std::size_t size() noexcept
140  {
141  return sizeof...(Tags);
142  }
143 
144 public:
145  inline constexpr DiscreteElement() = default;
146 
147  inline constexpr DiscreteElement(DiscreteElement const&) = default;
148 
149  inline constexpr DiscreteElement(DiscreteElement&&) = default;
150 
151  template <class... OTags>
152  explicit inline constexpr DiscreteElement(DiscreteElement<OTags> const&... other) noexcept
153  : m_values {take<Tags>(other...).uid()...}
154  {
155  }
156 
157  template <class... OTags>
158  explicit inline constexpr DiscreteElement(DiscreteElement<OTags...> const& other) noexcept
159  : m_values {other.template uid<Tags>()...}
160  {
161  }
162 
163  template <
164  class... Params,
165  class = std::enable_if_t<(std::is_integral_v<Params> && ...)>,
166  class = std::enable_if_t<(!is_discrete_element_v<Params> && ...)>,
167  class = std::enable_if_t<sizeof...(Params) == sizeof...(Tags)>>
168  explicit inline constexpr DiscreteElement(Params const&... params) noexcept
169  : m_values {static_cast<value_type>(params)...}
170  {
171  }
172 
173  constexpr inline DiscreteElement& operator=(DiscreteElement const& other) = default;
174 
175  constexpr inline DiscreteElement& operator=(DiscreteElement&& other) = default;
176 
177  template <class... OTags>
178  constexpr inline DiscreteElement& operator=(DiscreteElement<OTags...> const& other) noexcept
179  {
180  m_values = other.m_values;
181  return *this;
182  }
183 
184  template <class... OTags>
185  constexpr inline DiscreteElement& operator=(DiscreteElement<OTags...>&& other) noexcept
186  {
187  m_values = std::move(other.m_values);
188  return *this;
189  }
190 
191  template <class QueryTag>
192  value_type const& uid_or(value_type const& default_value) const&
193  {
194  DDC_IF_NVCC_THEN_PUSH_AND_SUPPRESS(implicit_return_from_non_void_function)
195  if constexpr (in_tags_v<QueryTag, tags_seq>) {
196  return m_values[type_seq_rank_v<QueryTag, tags_seq>];
197  } else {
198  return default_value;
199  }
200  DDC_IF_NVCC_THEN_POP
201  }
202 
203  template <class QueryTag>
204  inline constexpr value_type& uid() noexcept
205  {
206  using namespace ddc_detail;
207  static_assert(in_tags_v<QueryTag, tags_seq>, "requested Tag absent from DiscreteElement");
208  return m_values[type_seq_rank_v<QueryTag, tags_seq>];
209  }
210 
211  template <class QueryTag>
212  inline constexpr value_type const& uid() const noexcept
213  {
214  using namespace ddc_detail;
215  static_assert(in_tags_v<QueryTag, tags_seq>, "requested Tag absent from DiscreteElement");
216  return m_values[type_seq_rank_v<QueryTag, tags_seq>];
217  }
218 
219  template <std::size_t N = sizeof...(Tags)>
220  constexpr inline std::enable_if_t<N == 1, value_type&> uid() noexcept
221  {
222  return m_values[0];
223  }
224 
225  template <std::size_t N = sizeof...(Tags)>
226  constexpr inline std::enable_if_t<N == 1, value_type const&> uid() const noexcept
227  {
228  return m_values[0];
229  }
230 
231  template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
232  constexpr inline DiscreteElement& operator++()
233  {
234  ++m_values[0];
235  return *this;
236  }
237 
238  template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
239  constexpr inline DiscreteElement operator++(int)
240  {
241  DiscreteElement const tmp = *this;
242  ++m_values[0];
243  return tmp;
244  }
245 
246  template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
247  constexpr inline DiscreteElement& operator--()
248  {
249  ++m_values[0];
250  return *this;
251  }
252 
253  template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
254  constexpr inline DiscreteElement operator--(int)
255  {
256  DiscreteElement const tmp = *this;
257  ++m_values[0];
258  return tmp;
259  }
260 
261  template <class... OTags>
263  {
264  static_assert(type_seq_same_v<tags_seq, ddc_detail::TypeSeq<OTags...>>);
265  ((m_values[type_seq_rank_v<Tags, tags_seq>] += rhs.template get<Tags>()), ...);
266  return *this;
267  }
268 
269  template <
270  class IntegralType,
271  std::size_t N = sizeof...(Tags),
272  class = std::enable_if_t<N == 1>,
273  class = std::enable_if_t<std::is_integral_v<IntegralType>>>
274  constexpr inline DiscreteElement& operator+=(IntegralType const& rhs)
275  {
276  m_values[0] += rhs;
277  return *this;
278  }
279 
280  template <class... OTags>
282  {
283  static_assert(type_seq_same_v<tags_seq, ddc_detail::TypeSeq<OTags...>>);
284  ((m_values[type_seq_rank_v<Tags, tags_seq>] -= rhs.template get<Tags>()), ...);
285  return *this;
286  }
287 
288  template <
289  class IntegralType,
290  std::size_t N = sizeof...(Tags),
291  class = std::enable_if_t<N == 1>,
292  class = std::enable_if_t<std::is_integral_v<IntegralType>>>
293  constexpr inline DiscreteElement& operator-=(IntegralType const& rhs)
294  {
295  m_values[0] -= rhs;
296  return *this;
297  }
298 };
299 
300 inline std::ostream& operator<<(std::ostream& out, DiscreteElement<> const&)
301 {
302  out << "()";
303  return out;
304 }
305 
306 template <class Head, class... Tags>
307 std::ostream& operator<<(std::ostream& out, DiscreteElement<Head, Tags...> const& arr)
308 {
309  out << "(";
310  out << uid<Head>(arr);
311  ((out << ", " << uid<Tags>(arr)), ...);
312  out << ")";
313  return out;
314 }
315 
316 
317 template <class... Tags, class... OTags>
318 constexpr inline bool operator==(
319  DiscreteElement<Tags...> const& lhs,
320  DiscreteElement<OTags...> const& rhs) noexcept
321 {
322  return ((lhs.template uid<Tags>() == rhs.template uid<Tags>()) && ...);
323 }
324 
325 template <class... Tags, class... OTags>
326 constexpr inline bool operator!=(
327  DiscreteElement<Tags...> const& lhs,
328  DiscreteElement<OTags...> const& rhs) noexcept
329 {
330  return !(lhs == rhs);
331 }
332 
333 template <class Tag>
334 constexpr inline bool operator<(DiscreteElement<Tag> const& lhs, DiscreteElement<Tag> const& rhs)
335 {
336  return lhs.uid() < rhs.uid();
337 }
338 
339 template <class Tag>
340 constexpr inline bool operator<=(DiscreteElement<Tag> const& lhs, DiscreteElement<Tag> const& rhs)
341 {
342  return lhs.uid() <= rhs.uid();
343 }
344 
345 template <class Tag>
346 constexpr inline bool operator>(DiscreteElement<Tag> const& lhs, DiscreteElement<Tag> const& rhs)
347 {
348  return lhs.uid() > rhs.uid();
349 }
350 
351 template <class Tag>
352 constexpr inline bool operator>=(DiscreteElement<Tag> const& lhs, DiscreteElement<Tag> const& rhs)
353 {
354  return lhs.uid() >= rhs.uid();
355 }
356 
358 
359 template <class... Tags, class... OTags>
360 constexpr inline DiscreteElement<Tags...> operator+(
361  DiscreteElement<Tags...> const& lhs,
362  DiscreteVector<OTags...> const& rhs)
363 {
364  static_assert(type_seq_same_v<ddc_detail::TypeSeq<Tags...>, ddc_detail::TypeSeq<OTags...>>);
365  return DiscreteElement<Tags...>((uid<Tags>(lhs) + get<Tags>(rhs))...);
366 }
367 
368 template <
369  class Tag,
370  class IntegralType,
371  class = std::enable_if_t<std::is_integral_v<IntegralType>>,
372  class = std::enable_if_t<!is_discrete_vector_v<IntegralType>>>
373 constexpr inline DiscreteElement<Tag> operator+(
374  DiscreteElement<Tag> const& lhs,
375  IntegralType const& rhs)
376 {
377  return DiscreteElement<Tag>(uid<Tag>(lhs) + rhs);
378 }
379 
380 template <class... Tags, class... OTags>
381 constexpr inline DiscreteElement<Tags...> operator-(
382  DiscreteElement<Tags...> const& lhs,
383  DiscreteVector<OTags...> const& rhs)
384 {
385  static_assert(type_seq_same_v<ddc_detail::TypeSeq<Tags...>, ddc_detail::TypeSeq<OTags...>>);
386  return DiscreteElement<Tags...>((uid<Tags>(lhs) - get<Tags>(rhs))...);
387 }
388 
389 template <
390  class Tag,
391  class IntegralType,
392  class = std::enable_if_t<std::is_integral_v<IntegralType>>,
393  class = std::enable_if_t<!is_discrete_vector_v<IntegralType>>>
394 constexpr inline DiscreteElement<Tag> operator-(
395  DiscreteElement<Tag> const& lhs,
396  IntegralType const& rhs)
397 {
398  return DiscreteElement<Tag>(uid<Tag>(lhs) - rhs);
399 }
400 
402 
403 template <class... Tags, class... OTags>
404 constexpr inline DiscreteVector<Tags...> operator-(
405  DiscreteElement<Tags...> const& lhs,
406  DiscreteElement<OTags...> const& rhs)
407 {
408  static_assert(type_seq_same_v<ddc_detail::TypeSeq<Tags...>, ddc_detail::TypeSeq<OTags...>>);
409  return DiscreteVector<Tags...>((uid<Tags>(lhs) - uid<Tags>(rhs))...);
410 }
411 
412 } // namespace ddc
A DiscreteElement identifies an element of the discrete dimension.
Definition: discrete_element.hpp:124
constexpr DiscreteElement(DiscreteElement const &)=default
constexpr DiscreteElement(DiscreteElement< OTags... > const &other) noexcept
Definition: discrete_element.hpp:158
constexpr DiscreteElement()=default
constexpr DiscreteElement & operator+=(DiscreteVector< OTags... > const &rhs)
Definition: discrete_element.hpp:262
constexpr value_type const & uid() const noexcept
Definition: discrete_element.hpp:212
constexpr DiscreteElement & operator=(DiscreteElement const &other)=default
constexpr DiscreteElement & operator-=(DiscreteVector< OTags... > const &rhs)
Definition: discrete_element.hpp:281
constexpr DiscreteElement & operator=(DiscreteElement &&other)=default
constexpr DiscreteElement & operator=(DiscreteElement< OTags... > const &other) noexcept
Definition: discrete_element.hpp:178
constexpr DiscreteElement(Params const &... params) noexcept
Definition: discrete_element.hpp:168
constexpr DiscreteElement(DiscreteElement< OTags > const &... other) noexcept
Definition: discrete_element.hpp:152
constexpr value_type & uid() noexcept
Definition: discrete_element.hpp:204
DiscreteElementType value_type
Definition: discrete_element.hpp:137
constexpr DiscreteElement(DiscreteElement &&)=default
value_type const & uid_or(value_type const &default_value) const &
Definition: discrete_element.hpp:192
static constexpr std::size_t size() noexcept
Definition: discrete_element.hpp:139
constexpr std::enable_if_t< N==1, value_type const & > uid() const noexcept
Definition: discrete_element.hpp:226
constexpr DiscreteElement & operator=(DiscreteElement< OTags... > &&other) noexcept
Definition: discrete_element.hpp:185
constexpr std::enable_if_t< N==1, value_type & > uid() noexcept
Definition: discrete_element.hpp:220
A DiscreteVector is a vector in the discrete dimension.
Definition: discrete_vector.hpp:208
constexpr std::array< DiscreteElementType, sizeof...(Tags)> & array(DiscreteElement< Tags... > &v) noexcept
Returns a reference to the underlying std::array
Definition: discrete_element.hpp:102
Definition: aligned_allocator.hpp:9
constexpr bool operator!=(AlignedAllocator< T, NT > const &, AlignedAllocator< U, NU > const &) noexcept
Definition: aligned_allocator.hpp:63
std::ostream & operator<<(std::ostream &out, DiscreteElement<> const &)
Definition: discrete_element.hpp:300
constexpr DiscreteElement< Tags... > operator+(DiscreteElement< Tags... > const &lhs, DiscreteVector< OTags... > const &rhs)
right external binary operators: +, -
Definition: discrete_element.hpp:360
std::size_t DiscreteElementType
A DiscreteCoordElement is a scalar that identifies an element of the discrete dimension.
Definition: discrete_element.hpp:34
constexpr DiscreteElement< QueryTag > const & take(DiscreteElement< HeadTag > const &head, DiscreteElement< TailTags > const &... tags)
Definition: discrete_element.hpp:81
constexpr DiscreteElementType const & uid(DiscreteElement< Tag > const &tuple) noexcept
Definition: discrete_element.hpp:37
constexpr bool operator<(DiscreteElement< Tag > const &lhs, DiscreteElement< Tag > const &rhs)
Definition: discrete_element.hpp:334
constexpr bool is_discrete_vector_v
Definition: discrete_vector.hpp:28
constexpr bool is_discrete_element_v
Definition: discrete_element.hpp:29
constexpr bool operator>=(DiscreteElement< Tag > const &lhs, DiscreteElement< Tag > const &rhs)
Definition: discrete_element.hpp:352
constexpr bool operator<=(DiscreteElement< Tag > const &lhs, DiscreteElement< Tag > const &rhs)
Definition: discrete_element.hpp:340
constexpr DiscreteElementType const & uid_or(DiscreteElement< Tags... > const &tuple, DiscreteElementType const &default_value) noexcept
Definition: discrete_element.hpp:61
constexpr DiscreteDomain< QueryDDims... > select(DiscreteDomain< DDims... > const &domain)
Definition: discrete_domain.hpp:235
constexpr bool operator==(AlignedAllocator< T, NT > const &, AlignedAllocator< U, NU > const &) noexcept
Definition: aligned_allocator.hpp:57
constexpr bool operator>(DiscreteElement< Tag > const &lhs, DiscreteElement< Tag > const &rhs)
Definition: discrete_element.hpp:346
constexpr DiscreteElement< Tags... > operator-(DiscreteElement< Tags... > const &lhs, DiscreteVector< OTags... > const &rhs)
Definition: discrete_element.hpp:381
Definition: discrete_element.hpp:20