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