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