DDC 0.1.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 DiscreteElementType const& uid_or(
79 DiscreteElement<Tags...> const& tuple,
80 DiscreteElementType const& default_value) noexcept
81{
82 return tuple.template uid_or<QueryTag>(default_value);
83}
84
85template <class... QueryTags, class... Tags>
86KOKKOS_FUNCTION constexpr DiscreteElement<QueryTags...> select(
87 DiscreteElement<Tags...> const& arr) noexcept
88{
89 return DiscreteElement<QueryTags...>(arr);
90}
91
92template <class... QueryTags, class... Tags>
93KOKKOS_FUNCTION constexpr DiscreteElement<QueryTags...> select(
94 DiscreteElement<Tags...>&& arr) noexcept
95{
96 return DiscreteElement<QueryTags...>(std::move(arr));
97}
98
99/// Returns a reference towards the DiscreteElement that contains the QueryTag
100template <
101 class QueryTag,
102 class HeadDElem,
103 class... TailDElems,
104 std::enable_if_t<
105 is_discrete_element_v<HeadDElem> && (is_discrete_element_v<TailDElems> && ...),
106 int>
107 = 1>
108KOKKOS_FUNCTION constexpr auto const& take(HeadDElem const& head, TailDElems const&... tail)
109{
110 DDC_IF_NVCC_THEN_PUSH_AND_SUPPRESS(implicit_return_from_non_void_function)
111 if constexpr (type_seq_contains_v<detail::TypeSeq<QueryTag>, to_type_seq_t<HeadDElem>>) {
112 static_assert(
113 (!type_seq_contains_v<detail::TypeSeq<QueryTag>, to_type_seq_t<TailDElems>> && ...),
114 "ERROR: tag redundant");
115 return head;
116 } else {
117 static_assert(sizeof...(TailDElems) > 0, "ERROR: tag not found");
118 return take<QueryTag>(tail...);
119 }
120 DDC_IF_NVCC_THEN_POP
121}
122
123namespace detail {
124
125/// Returns a reference to the underlying `std::array`
126template <class... Tags>
127KOKKOS_FUNCTION constexpr std::array<DiscreteElementType, sizeof...(Tags)>& array(
128 DiscreteElement<Tags...>& v) noexcept
129{
130 return v.m_values;
131}
132
133/// Returns a reference to the underlying `std::array`
134template <class... Tags>
135KOKKOS_FUNCTION constexpr std::array<DiscreteElementType, sizeof...(Tags)> const& array(
136 DiscreteElement<Tags...> const& v) noexcept
137{
138 return v.m_values;
139}
140
141} // namespace detail
142
143/** A DiscreteElement identifies an element of the discrete dimension
144 *
145 * Each one is tagged by its associated dimensions.
146 */
147template <class... Tags>
148class DiscreteElement
149{
150 using tags_seq = detail::TypeSeq<Tags...>;
151
152 friend KOKKOS_FUNCTION constexpr std::array<DiscreteElementType, sizeof...(Tags)>& detail::
153 array<Tags...>(DiscreteElement<Tags...>& v) noexcept;
154
155 friend KOKKOS_FUNCTION constexpr std::array<DiscreteElementType, sizeof...(Tags)> const&
156 detail::array<Tags...>(DiscreteElement<Tags...> const& v) noexcept;
157
158private:
159 std::array<DiscreteElementType, sizeof...(Tags)> m_values;
160
161public:
162 using value_type = DiscreteElementType;
163
164 static KOKKOS_FUNCTION constexpr std::size_t size() noexcept
165 {
166 return sizeof...(Tags);
167 }
168
169public:
170 KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteElement() = default;
171
172 KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteElement(DiscreteElement const&) = default;
173
174 KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteElement(DiscreteElement&&) = default;
175
176 template <class... DElems, class = std::enable_if_t<(is_discrete_element_v<DElems> && ...)>>
177 KOKKOS_FUNCTION constexpr explicit DiscreteElement(DElems const&... delems) noexcept
178 : m_values {take<Tags>(delems...).template uid<Tags>()...}
179 {
180 }
181
182 template <
183 class... Params,
184 class = std::enable_if_t<(!is_discrete_element_v<Params> && ...)>,
185 class = std::enable_if_t<(std::is_integral_v<Params> && ...)>,
186 class = std::enable_if_t<sizeof...(Params) == sizeof...(Tags)>>
187 KOKKOS_FUNCTION constexpr explicit DiscreteElement(Params const&... params) noexcept
188 : m_values {static_cast<value_type>(params)...}
189 {
190 }
191
192 KOKKOS_DEFAULTED_FUNCTION ~DiscreteElement() = default;
193
194 KOKKOS_DEFAULTED_FUNCTION DiscreteElement& operator=(DiscreteElement const& other) = default;
195
196 KOKKOS_DEFAULTED_FUNCTION DiscreteElement& operator=(DiscreteElement&& other) = default;
197
198 template <class QueryTag>
199 KOKKOS_FUNCTION constexpr value_type const& uid_or(value_type const& default_value) const&
200 {
201 DDC_IF_NVCC_THEN_PUSH_AND_SUPPRESS(implicit_return_from_non_void_function)
202 if constexpr (in_tags_v<QueryTag, tags_seq>) {
203 return m_values[type_seq_rank_v<QueryTag, tags_seq>];
204 } else {
205 return default_value;
206 }
207 DDC_IF_NVCC_THEN_POP
208 }
209
210 template <class QueryTag>
211 KOKKOS_FUNCTION constexpr value_type& uid() noexcept
212 {
213 static_assert(in_tags_v<QueryTag, tags_seq>, "requested Tag absent from DiscreteElement");
214 return m_values[type_seq_rank_v<QueryTag, tags_seq>];
215 }
216
217 template <class QueryTag>
218 KOKKOS_FUNCTION constexpr value_type const& uid() const noexcept
219 {
220 static_assert(in_tags_v<QueryTag, tags_seq>, "requested Tag absent from DiscreteElement");
221 return m_values[type_seq_rank_v<QueryTag, tags_seq>];
222 }
223
224 template <std::size_t N = sizeof...(Tags)>
225 KOKKOS_FUNCTION constexpr std::enable_if_t<N == 1, value_type&> uid() noexcept
226 {
227 return m_values[0];
228 }
229
230 template <std::size_t N = sizeof...(Tags)>
231 KOKKOS_FUNCTION constexpr std::enable_if_t<N == 1, value_type const&> uid() const noexcept
232 {
233 return m_values[0];
234 }
235
236 template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
237 KOKKOS_FUNCTION constexpr DiscreteElement& operator++()
238 {
239 ++m_values[0];
240 return *this;
241 }
242
243 template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
244 KOKKOS_FUNCTION constexpr DiscreteElement operator++(int)
245 {
246 DiscreteElement const tmp = *this;
247 ++m_values[0];
248 return tmp;
249 }
250
251 template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
252 KOKKOS_FUNCTION constexpr DiscreteElement& operator--()
253 {
254 --m_values[0];
255 return *this;
256 }
257
258 template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
259 KOKKOS_FUNCTION constexpr DiscreteElement operator--(int)
260 {
261 DiscreteElement const tmp = *this;
262 --m_values[0];
263 return tmp;
264 }
265
266 template <class... OTags>
267 KOKKOS_FUNCTION constexpr DiscreteElement& operator+=(DiscreteVector<OTags...> const& rhs)
268 {
269 static_assert(((type_seq_contains_v<detail::TypeSeq<OTags>, tags_seq>) && ...));
270 ((m_values[type_seq_rank_v<OTags, tags_seq>] += rhs.template get<OTags>()), ...);
271 return *this;
272 }
273
274 template <
275 class IntegralType,
276 std::size_t N = sizeof...(Tags),
277 class = std::enable_if_t<N == 1>,
278 class = std::enable_if_t<std::is_integral_v<IntegralType>>>
279 KOKKOS_FUNCTION constexpr DiscreteElement& operator+=(IntegralType const& rhs)
280 {
281 m_values[0] += rhs;
282 return *this;
283 }
284
285 template <class... OTags>
286 KOKKOS_FUNCTION constexpr DiscreteElement& operator-=(DiscreteVector<OTags...> const& rhs)
287 {
288 static_assert(((type_seq_contains_v<detail::TypeSeq<OTags>, tags_seq>) && ...));
289 ((m_values[type_seq_rank_v<OTags, tags_seq>] -= rhs.template get<OTags>()), ...);
290 return *this;
291 }
292
293 template <
294 class IntegralType,
295 std::size_t N = sizeof...(Tags),
296 class = std::enable_if_t<N == 1>,
297 class = std::enable_if_t<std::is_integral_v<IntegralType>>>
298 KOKKOS_FUNCTION constexpr DiscreteElement& operator-=(IntegralType const& rhs)
299 {
300 m_values[0] -= rhs;
301 return *this;
302 }
303};
304
305inline std::ostream& operator<<(std::ostream& out, DiscreteElement<> const&)
306{
307 out << "()";
308 return out;
309}
310
311template <class Head, class... Tags>
312std::ostream& operator<<(std::ostream& out, DiscreteElement<Head, Tags...> const& arr)
313{
314 out << "(";
315 out << uid<Head>(arr);
316 ((out << ", " << uid<Tags>(arr)), ...);
317 out << ")";
318 return out;
319}
320
321
322template <class... Tags, class... OTags>
323KOKKOS_FUNCTION constexpr bool operator==(
324 DiscreteElement<Tags...> const& lhs,
325 DiscreteElement<OTags...> const& rhs) noexcept
326{
327 return ((lhs.template uid<Tags>() == rhs.template uid<Tags>()) && ...);
328}
329
330#if !defined(__cpp_impl_three_way_comparison) || __cpp_impl_three_way_comparison < 201902L
331// In C++20, `a!=b` shall be automatically translated by the compiler to `!(a==b)`
332template <class... Tags, class... OTags>
333KOKKOS_FUNCTION constexpr bool operator!=(
334 DiscreteElement<Tags...> const& lhs,
335 DiscreteElement<OTags...> const& rhs) noexcept
336{
337 return !(lhs == rhs);
338}
339#endif
340
341template <class Tag>
342KOKKOS_FUNCTION constexpr bool operator<(
343 DiscreteElement<Tag> const& lhs,
344 DiscreteElement<Tag> const& rhs)
345{
346 return lhs.uid() < rhs.uid();
347}
348
349template <class Tag>
350KOKKOS_FUNCTION constexpr bool operator<=(
351 DiscreteElement<Tag> const& lhs,
352 DiscreteElement<Tag> const& rhs)
353{
354 return lhs.uid() <= rhs.uid();
355}
356
357template <class Tag>
358KOKKOS_FUNCTION constexpr bool operator>(
359 DiscreteElement<Tag> const& lhs,
360 DiscreteElement<Tag> const& rhs)
361{
362 return lhs.uid() > rhs.uid();
363}
364
365template <class Tag>
366KOKKOS_FUNCTION constexpr bool operator>=(
367 DiscreteElement<Tag> const& lhs,
368 DiscreteElement<Tag> const& rhs)
369{
370 return lhs.uid() >= rhs.uid();
371}
372
373/// right external binary operators: +, -
374
375template <class... Tags, class... OTags>
376KOKKOS_FUNCTION constexpr DiscreteElement<Tags...> operator+(
377 DiscreteElement<Tags...> const& lhs,
378 DiscreteVector<OTags...> const& rhs)
379{
380 using detail::TypeSeq;
381 static_assert(((type_seq_contains_v<TypeSeq<OTags>, TypeSeq<Tags...>>) && ...));
382 DiscreteElement<Tags...> result(lhs);
383 result += rhs;
384 return result;
385}
386
387template <
388 class Tag,
389 class IntegralType,
390 class = std::enable_if_t<std::is_integral_v<IntegralType>>,
391 class = std::enable_if_t<!is_discrete_vector_v<IntegralType>>>
392KOKKOS_FUNCTION constexpr DiscreteElement<Tag> operator+(
393 DiscreteElement<Tag> const& lhs,
394 IntegralType const& rhs)
395{
396 return DiscreteElement<Tag>(uid<Tag>(lhs) + rhs);
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 return DiscreteElement<Tag>(uid<Tag>(lhs) - rhs);
421}
422
423/// binary operator: -
424
425template <class... Tags, class... OTags>
426KOKKOS_FUNCTION constexpr DiscreteVector<Tags...> operator-(
427 DiscreteElement<Tags...> const& lhs,
428 DiscreteElement<OTags...> const& rhs)
429{
430 static_assert(type_seq_same_v<detail::TypeSeq<Tags...>, detail::TypeSeq<OTags...>>);
431 return DiscreteVector<Tags...>((uid<Tags>(lhs) - uid<Tags>(rhs))...);
432}
433
434} // 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 value_type const & uid_or(value_type const &default_value) const &
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 DiscreteElementType const & uid_or(DiscreteElement< Tags... > const &tuple, DiscreteElementType const &default_value) noexcept
KOKKOS_FUNCTION constexpr bool operator==(DiscreteElement< Tags... > const &lhs, DiscreteElement< OTags... > const &rhs) noexcept
KOKKOS_FUNCTION constexpr DiscreteElement< QueryTags... > select(DiscreteElement< Tags... > &&arr) 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 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