DDC 0.1.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
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 static KOKKOS_FUNCTION constexpr std::size_t size() noexcept
272 {
273 return sizeof...(Tags);
274 }
275
276public:
277 KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteVector() = default;
278
279 KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteVector(DiscreteVector const&) = default;
280
282
283 template <class... DVects, class = std::enable_if_t<(is_discrete_vector_v<DVects> && ...)>>
284 KOKKOS_FUNCTION constexpr explicit DiscreteVector(DVects const&... delems) noexcept
285 : m_values {take<Tags>(delems...).template get<Tags>()...}
286 {
287 }
288
289 template <
290 class... Params,
291 class = std::enable_if_t<(!is_discrete_vector_v<Params> && ...)>,
292 class = std::enable_if_t<(std::is_convertible_v<Params, DiscreteVectorElement> && ...)>,
293 class = std::enable_if_t<sizeof...(Params) == sizeof...(Tags)>>
294 KOKKOS_FUNCTION constexpr explicit DiscreteVector(Params const&... params) noexcept
295 : m_values {static_cast<DiscreteVectorElement>(params)...}
296 {
297 }
298
300
302 = default;
303
305
306 template <class... OTags>
307 KOKKOS_FUNCTION constexpr bool operator==(DiscreteVector<OTags...> const& rhs) const noexcept
308 {
309 return ((m_values[type_seq_rank_v<Tags, tags_seq>] == rhs.template get<Tags>()) && ...);
310 }
311
312#if !defined(__cpp_impl_three_way_comparison) || __cpp_impl_three_way_comparison < 201902L
313 // In C++20, `a!=b` shall be automatically translated by the compiler to `!(a==b)`
314 template <class... OTags>
315 KOKKOS_FUNCTION constexpr bool operator!=(DiscreteVector<OTags...> const& rhs) const noexcept
316 {
317 return !(*this == rhs);
318 }
319#endif
320
321 template <class QueryTag>
322 KOKKOS_FUNCTION constexpr DiscreteVectorElement& get() noexcept
323 {
324 static_assert(in_tags_v<QueryTag, tags_seq>, "requested Tag absent from DiscreteVector");
325 return m_values[type_seq_rank_v<QueryTag, tags_seq>];
326 }
327
328 template <class QueryTag>
329 KOKKOS_FUNCTION constexpr DiscreteVectorElement const& get() const noexcept
330 {
331 static_assert(in_tags_v<QueryTag, tags_seq>, "requested Tag absent from DiscreteVector");
332 return m_values[type_seq_rank_v<QueryTag, tags_seq>];
333 }
334
335 template <class QueryTag>
336 KOKKOS_FUNCTION constexpr DiscreteVectorElement const& get_or(
337 DiscreteVectorElement const& default_value) const&
338 {
339 DDC_IF_NVCC_THEN_PUSH_AND_SUPPRESS(implicit_return_from_non_void_function)
340 if constexpr (in_tags_v<QueryTag, tags_seq>) {
341 return m_values[type_seq_rank_v<QueryTag, tags_seq>];
342 } else {
343 return default_value;
344 }
345 DDC_IF_NVCC_THEN_POP
346 }
347
348 template <std::size_t N = sizeof...(Tags)>
349 KOKKOS_FUNCTION constexpr std::enable_if_t<N == 1, DiscreteVectorElement const&> value()
350 const noexcept
351 {
352 return m_values[0];
353 }
354
355 template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
357 {
358 ++m_values[0];
359 return *this;
360 }
361
362 template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
364 {
365 DiscreteVector const tmp = *this;
366 ++m_values[0];
367 return tmp;
368 }
369
370 template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
372 {
373 --m_values[0];
374 return *this;
375 }
376
377 template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
379 {
380 DiscreteVector const tmp = *this;
381 --m_values[0];
382 return tmp;
383 }
384
385 template <class... OTags>
386 KOKKOS_FUNCTION constexpr DiscreteVector& operator+=(DiscreteVector<OTags...> const& rhs)
387 {
388 static_assert(((type_seq_contains_v<detail::TypeSeq<OTags>, tags_seq>) && ...));
389 ((m_values[type_seq_rank_v<OTags, tags_seq>] += rhs.template get<OTags>()), ...);
390 return *this;
391 }
392
393 template <
394 class IntegralType,
395 std::size_t N = sizeof...(Tags),
396 class = std::enable_if_t<N == 1>,
397 class = std::enable_if_t<std::is_integral_v<IntegralType>>>
398 KOKKOS_FUNCTION constexpr DiscreteVector& operator+=(IntegralType const& rhs)
399 {
400 m_values[0] += rhs;
401 return *this;
402 }
403
404 template <class... OTags>
405 KOKKOS_FUNCTION constexpr DiscreteVector& operator-=(DiscreteVector<OTags...> const& rhs)
406 {
407 static_assert(((type_seq_contains_v<detail::TypeSeq<OTags>, tags_seq>) && ...));
408 ((m_values[type_seq_rank_v<OTags, tags_seq>] -= rhs.template get<OTags>()), ...);
409 return *this;
410 }
411
412 template <
413 class IntegralType,
414 std::size_t N = sizeof...(Tags),
415 class = std::enable_if_t<N == 1>,
416 class = std::enable_if_t<std::is_integral_v<IntegralType>>>
417 KOKKOS_FUNCTION constexpr DiscreteVector& operator-=(IntegralType const& rhs)
418 {
419 m_values[0] -= rhs;
420 return *this;
421 }
422
423 template <class... OTags>
424 KOKKOS_FUNCTION constexpr DiscreteVector& operator*=(DiscreteVector<OTags...> const& rhs)
425 {
426 static_assert(((type_seq_contains_v<detail::TypeSeq<OTags>, tags_seq>) && ...));
427 ((m_values[type_seq_rank_v<OTags, tags_seq>] *= rhs.template get<OTags>()), ...);
428 return *this;
429 }
430};
431
432template <class Tag>
433KOKKOS_FUNCTION constexpr bool operator<(
434 DiscreteVector<Tag> const& lhs,
435 DiscreteVector<Tag> const& rhs)
436{
437 return lhs.value() < rhs.value();
438}
439
440template <class Tag, class IntegralType>
441KOKKOS_FUNCTION constexpr bool operator<(DiscreteVector<Tag> const& lhs, IntegralType const& rhs)
442{
443 return lhs.value() < rhs;
444}
445
446inline std::ostream& operator<<(std::ostream& out, DiscreteVector<> const&)
447{
448 out << "()";
449 return out;
450}
451
452template <class Head, class... Tags>
453std::ostream& operator<<(std::ostream& out, DiscreteVector<Head, Tags...> const& arr)
454{
455 out << "(";
456 out << get<Head>(arr);
457 ((out << ", " << get<Tags>(arr)), ...);
458 out << ")";
459 return out;
460}
461
462} // 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