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