DDC 0.0.0

a discrete domain computation library

discrete_domain.hpp
1 // SPDX-License-Identifier: MIT
2 
3 #pragma once
4 
5 #include <cassert>
6 #include <cstdint>
7 #include <tuple>
8 
9 #include "ddc/coordinate.hpp"
10 #include "ddc/detail/type_seq.hpp"
11 #include "ddc/discrete_element.hpp"
12 #include "ddc/discrete_vector.hpp"
13 
14 namespace ddc {
15 
16 template <class DDim>
17 struct DiscreteDomainIterator;
18 
19 template <class... DDims>
20 class DiscreteDomain;
21 
22 template <class... DDims>
24 {
25  template <class...>
26  friend class DiscreteDomain;
27 
28 public:
30 
31  using mlength_type = DiscreteVector<DDims...>;
32 
33 private:
34  DiscreteElement<DDims...> m_element_begin;
35 
36  DiscreteElement<DDims...> m_element_end;
37 
38 public:
39  static constexpr std::size_t rank()
40  {
41  return (0 + ... + DDims::rank());
42  }
43 
44  DiscreteDomain() = default;
45 
47  template <class... ODDims>
48  explicit constexpr DiscreteDomain(DiscreteDomain<ODDims...> const& domain)
49  : m_element_begin(domain.front())
50  , m_element_end(domain.front() + domain.extents())
51  {
52  }
53 
54  // Use SFINAE to disambiguate with the copy constructor.
55  // Note that SFINAE may be redundant because a template constructor should not be selected as a copy constructor.
56  template <std::size_t N = sizeof...(DDims), class = std::enable_if_t<(N != 1)>>
57  explicit constexpr DiscreteDomain(DiscreteDomain<DDims> const&... domains)
58  : m_element_begin(domains.front()...)
59  , m_element_end((domains.front() + domains.extents())...)
60  {
61  }
62 
68  [[deprecated]] constexpr DiscreteDomain(mlength_type const& size)
69  : m_element_begin(
70  (get<DDims>(size) - get<DDims>(size))...) // Hack to have expansion of zero
71  , m_element_end(get<DDims>(size)...)
72  {
73  }
74 
79  constexpr DiscreteDomain(discrete_element_type const& element_begin, mlength_type const& size)
80  : m_element_begin(element_begin)
81  , m_element_end(element_begin + size)
82  {
83  }
84 
85  DiscreteDomain(DiscreteDomain const& x) = default;
86 
88 
89  ~DiscreteDomain() = default;
90 
91  DiscreteDomain& operator=(DiscreteDomain const& x) = default;
92 
94 
95  template <class... ODims>
96  constexpr bool operator==(DiscreteDomain<ODims...> const& other) const
97  {
98  return m_element_begin == other.m_element_begin && m_element_end == other.m_element_end;
99  }
100 
101 #if __cplusplus <= 201703L
102  // Shall not be necessary anymore in C++20
103  // `a!=b` shall be translated by the compiler to `!(a==b)`
104  constexpr bool operator!=(DiscreteDomain const& other) const
105  {
106  return !(*this == other);
107  }
108 #endif
109 
110  std::size_t size() const
111  {
112  return (1ul * ... * (uid<DDims>(m_element_end) - uid<DDims>(m_element_begin)));
113  }
114 
115  constexpr mlength_type extents() const noexcept
116  {
117  return mlength_type((uid<DDims>(m_element_end) - uid<DDims>(m_element_begin))...);
118  }
119 
120  template <class QueryDDim>
121  inline constexpr DiscreteVector<QueryDDim> extent() const noexcept
122  {
124  uid<QueryDDim>(m_element_end) - uid<QueryDDim>(m_element_begin));
125  }
126 
127  constexpr discrete_element_type front() const noexcept
128  {
129  return m_element_begin;
130  }
131 
132  constexpr discrete_element_type back() const noexcept
133  {
134  return discrete_element_type((uid<DDims>(m_element_end) - 1)...);
135  }
136 
138  {
139  return DiscreteDomain(front(), n);
140  }
141 
143  {
144  return DiscreteDomain(front() + size() - n, n);
145  }
146 
148  {
149  return take_last(size() - n);
150  }
151 
153  {
154  return take_first(size() - n);
155  }
156 
158  {
159  return remove_first(n1).remove_last(n2);
160  }
161 
162  template <class... ODDims>
163  constexpr auto restrict(DiscreteDomain<ODDims...> const& odomain) const
164  {
165  assert(((uid<ODDims>(m_element_begin) <= uid<ODDims>(odomain.m_element_begin)) && ...));
166  assert(((uid<ODDims>(m_element_end) >= uid<ODDims>(odomain.m_element_end)) && ...));
167  const DiscreteVector<DDims...> myextents = extents();
168  const DiscreteVector<ODDims...> oextents = odomain.extents();
169  return DiscreteDomain(
171  (uid_or<DDims>(odomain.m_element_begin, uid<DDims>(m_element_begin)))...),
172  DiscreteVector<DDims...>((get_or<DDims>(oextents, get<DDims>(myextents)))...));
173  }
174 
175  constexpr bool empty() const noexcept
176  {
177  return size() == 0;
178  }
179 
180  constexpr explicit operator bool()
181  {
182  return !empty();
183  }
184 
185  template <
186  std::size_t N = sizeof...(DDims),
187  class DDim0 = std::enable_if_t<N == 1, std::tuple_element_t<0, std::tuple<DDims...>>>>
188  auto begin() const
189  {
191  }
192 
193  template <
194  std::size_t N = sizeof...(DDims),
195  class DDim0 = std::enable_if_t<N == 1, std::tuple_element_t<0, std::tuple<DDims...>>>>
196  auto end() const
197  {
198  return DiscreteDomainIterator<DDim0>(m_element_end);
199  }
200 
201  template <
202  std::size_t N = sizeof...(DDims),
203  class DDim0 = std::enable_if_t<N == 1, std::tuple_element_t<0, std::tuple<DDims...>>>>
204  auto cbegin() const
205  {
207  }
208 
209  template <
210  std::size_t N = sizeof...(DDims),
211  class DDim0 = std::enable_if_t<N == 1, std::tuple_element_t<0, std::tuple<DDims...>>>>
212  auto cend() const
213  {
214  return DiscreteDomainIterator<DDim0>(m_element_end);
215  }
216 
217  template <
218  std::size_t N = sizeof...(DDims),
219  class = std::enable_if_t<N == 1, std::tuple_element_t<0, std::tuple<DDims...>>>>
220  constexpr decltype(auto) operator[](std::size_t __n)
221  {
222  return begin()[__n];
223  }
224 
225  template <
226  std::size_t N = sizeof...(DDims),
227  class = std::enable_if_t<N == 1, std::tuple_element_t<0, std::tuple<DDims...>>>>
228  constexpr decltype(auto) operator[](std::size_t __n) const
229  {
230  return begin()[__n];
231  }
232 };
233 
234 template <class... QueryDDims, class... DDims>
235 constexpr DiscreteDomain<QueryDDims...> select(DiscreteDomain<DDims...> const& domain)
236 {
237  return DiscreteDomain<QueryDDims...>(
238  select<QueryDDims...>(domain.front()),
239  select<QueryDDims...>(domain.extents()));
240 }
241 
242 template <class... QueryDDims, class... DDims>
243 constexpr DiscreteVector<QueryDDims...> extents(DiscreteDomain<DDims...> const& domain) noexcept
244 {
245  return DiscreteVector<QueryDDims...>(select<QueryDDims>(domain).size()...);
246 }
247 
248 template <class... QueryDDims, class... DDims>
249 constexpr DiscreteElement<QueryDDims...> front(DiscreteDomain<DDims...> const& domain) noexcept
250 {
251  return DiscreteElement<QueryDDims...>(select<QueryDDims>(domain).front()...);
252 }
253 
254 template <class... QueryDDims, class... DDims>
255 constexpr DiscreteElement<QueryDDims...> back(DiscreteDomain<DDims...> const& domain) noexcept
256 {
257  return DiscreteElement<QueryDDims...>(select<QueryDDims>(domain).back()...);
258 }
259 
260 template <class... QueryDDims, class... DDims>
262  DiscreteDomain<DDims...> const& domain,
263  DiscreteElement<QueryDDims...> const& icoord) noexcept
264 {
265  return ddc::Coordinate<QueryDDims...>(
266  select<QueryDDims>(domain).coordinate(select<QueryDDims>(icoord))...);
267 }
268 
269 template <class... QueryDDims, class... DDims>
270 ddc::Coordinate<QueryDDims...> rmin(DiscreteDomain<DDims...> const& domain) noexcept
271 {
272  return ddc::Coordinate<QueryDDims...>(select<QueryDDims>(domain).rmin()...);
273 }
274 
275 template <class... QueryDDims, class... DDims>
276 ddc::Coordinate<QueryDDims...> rmax(DiscreteDomain<DDims...> const& domain) noexcept
277 {
278  return ddc::Coordinate<QueryDDims...>(select<QueryDDims>(domain).rmax()...);
279 }
280 
281 namespace ddc_detail {
282 
283 template <class QueryDDimSeq>
284 struct Selection;
285 
286 template <class... QueryDDims>
287 struct Selection<ddc_detail::TypeSeq<QueryDDims...>>
288 {
289  template <class Domain>
290  static constexpr auto select(Domain const& domain)
291  {
292  return ddc::select<QueryDDims...>(domain);
293  }
294 };
295 
296 } // namespace ddc_detail
297 
298 template <class QueryDDimSeq, class... DDims>
299 constexpr auto select_by_type_seq(DiscreteDomain<DDims...> const& domain)
300 {
302 }
303 
304 template <class DDim>
306 {
307 private:
309 
310 public:
311  using iterator_category = std::random_access_iterator_tag;
312 
314 
315  using difference_type = std::ptrdiff_t;
316 
318 
319  constexpr explicit DiscreteDomainIterator(DiscreteElement<DDim> __value) : m_value(__value) {}
320 
321  constexpr DiscreteElement<DDim> operator*() const noexcept
322  {
323  return m_value;
324  }
325 
327  {
328  ++m_value.uid();
329  return *this;
330  }
331 
333  {
334  auto __tmp = *this;
335  ++*this;
336  return __tmp;
337  }
338 
340  {
341  --m_value.uid();
342  return *this;
343  }
344 
346  {
347  auto __tmp = *this;
348  --*this;
349  return __tmp;
350  }
351 
353  {
354  if (__n >= difference_type(0))
355  m_value.uid() += static_cast<DiscreteElementType>(__n);
356  else
357  m_value.uid() -= static_cast<DiscreteElementType>(-__n);
358  return *this;
359  }
360 
362  {
363  if (__n >= difference_type(0))
364  m_value.uid() -= static_cast<DiscreteElementType>(__n);
365  else
366  m_value.uid() += static_cast<DiscreteElementType>(-__n);
367  return *this;
368  }
369 
371  {
372  return m_value + __n;
373  }
374 
375  friend constexpr bool operator==(
376  DiscreteDomainIterator const& xx,
377  DiscreteDomainIterator const& yy)
378  {
379  return xx.m_value == yy.m_value;
380  }
381 
382  friend constexpr bool operator!=(
383  DiscreteDomainIterator const& xx,
384  DiscreteDomainIterator const& yy)
385  {
386  return xx.m_value != yy.m_value;
387  }
388 
389  friend constexpr bool operator<(
390  DiscreteDomainIterator const& xx,
391  DiscreteDomainIterator const& yy)
392  {
393  return xx.m_value < yy.m_value;
394  }
395 
396  friend constexpr bool operator>(
397  DiscreteDomainIterator const& xx,
398  DiscreteDomainIterator const& yy)
399  {
400  return yy < xx;
401  }
402 
403  friend constexpr bool operator<=(
404  DiscreteDomainIterator const& xx,
405  DiscreteDomainIterator const& yy)
406  {
407  return !(yy < xx);
408  }
409 
410  friend constexpr bool operator>=(
411  DiscreteDomainIterator const& xx,
412  DiscreteDomainIterator const& yy)
413  {
414  return !(xx < yy);
415  }
416 
419  difference_type __n)
420  {
421  return __i += __n;
422  }
423 
425  difference_type __n,
427  {
428  return __i += __n;
429  }
430 
433  difference_type __n)
434  {
435  return __i -= __n;
436  }
437 
438  friend constexpr difference_type operator-(
439  DiscreteDomainIterator const& xx,
440  DiscreteDomainIterator const& yy)
441  {
442  return (yy.m_value > xx.m_value) ? (-static_cast<difference_type>(yy.m_value - xx.m_value))
443  : (xx.m_value - yy.m_value);
444  }
445 };
446 
447 } // namespace ddc
Definition: discrete_domain.hpp:24
DiscreteDomain & operator=(DiscreteDomain &&x)=default
DiscreteVector< DDims... > mlength_type
Definition: discrete_domain.hpp:31
auto begin() const
Definition: discrete_domain.hpp:188
constexpr decltype(auto) operator[](std::size_t __n)
Definition: discrete_domain.hpp:220
constexpr bool empty() const noexcept
Definition: discrete_domain.hpp:175
DiscreteDomain(DiscreteDomain const &x)=default
constexpr DiscreteDomain remove(mlength_type n1, mlength_type n2) const
Definition: discrete_domain.hpp:157
friend class DiscreteDomain
Definition: discrete_domain.hpp:26
auto cbegin() const
Definition: discrete_domain.hpp:204
constexpr discrete_element_type back() const noexcept
Definition: discrete_domain.hpp:132
std::size_t size() const
Definition: discrete_domain.hpp:110
constexpr DiscreteDomain(DiscreteDomain< ODDims... > const &domain)
Construct a DiscreteDomain from a reordered copy of domain
Definition: discrete_domain.hpp:48
constexpr auto restrict(DiscreteDomain< ODDims... > const &odomain) const
Definition: discrete_domain.hpp:163
constexpr DiscreteDomain take_first(mlength_type n) const
Definition: discrete_domain.hpp:137
constexpr discrete_element_type front() const noexcept
Definition: discrete_domain.hpp:127
constexpr mlength_type extents() const noexcept
Definition: discrete_domain.hpp:115
DiscreteDomain & operator=(DiscreteDomain const &x)=default
auto cend() const
Definition: discrete_domain.hpp:212
constexpr DiscreteDomain(DiscreteDomain< DDims > const &... domains)
Definition: discrete_domain.hpp:57
constexpr DiscreteDomain take_last(mlength_type n) const
Definition: discrete_domain.hpp:142
~DiscreteDomain()=default
constexpr DiscreteVector< QueryDDim > extent() const noexcept
Definition: discrete_domain.hpp:121
constexpr DiscreteDomain(discrete_element_type const &element_begin, mlength_type const &size)
Construct a DiscreteDomain starting from element_begin with size points.
Definition: discrete_domain.hpp:79
static constexpr std::size_t rank()
Definition: discrete_domain.hpp:39
constexpr bool operator==(DiscreteDomain< ODims... > const &other) const
Definition: discrete_domain.hpp:96
constexpr bool operator!=(DiscreteDomain const &other) const
Definition: discrete_domain.hpp:104
constexpr DiscreteDomain remove_last(mlength_type n) const
Definition: discrete_domain.hpp:152
DiscreteDomain(DiscreteDomain &&x)=default
auto end() const
Definition: discrete_domain.hpp:196
constexpr DiscreteDomain(mlength_type const &size)
Construct a DiscreteDomain starting from (0, ..., 0) with size points.
Definition: discrete_domain.hpp:68
DiscreteDomain()=default
DiscreteElement< DDims... > discrete_element_type
Definition: discrete_domain.hpp:29
constexpr decltype(auto) operator[](std::size_t __n) const
Definition: discrete_domain.hpp:228
constexpr DiscreteDomain remove_first(mlength_type n) const
Definition: discrete_domain.hpp:147
constexpr value_type & uid() noexcept
Definition: discrete_element.hpp:204
A DiscreteVector is a vector in the discrete dimension.
Definition: discrete_vector.hpp:208
Definition: discrete_domain.hpp:284
Definition: aligned_allocator.hpp:9
ddc::Coordinate< QueryDDims... > rmin(DiscreteDomain< DDims... > const &domain) noexcept
Definition: discrete_domain.hpp:270
constexpr DiscreteVector< QueryDDims... > extents(DiscreteDomain< DDims... > const &domain) noexcept
Definition: discrete_domain.hpp:243
ddc::Coordinate< QueryDDims... > coordinate(DiscreteDomain< DDims... > const &domain, DiscreteElement< QueryDDims... > const &icoord) noexcept
Definition: discrete_domain.hpp:261
std::size_t DiscreteElementType
A DiscreteCoordElement is a scalar that identifies an element of the discrete dimension.
Definition: discrete_element.hpp:34
constexpr DiscreteElement< QueryDDims... > back(DiscreteDomain< DDims... > const &domain) noexcept
Definition: discrete_domain.hpp:255
constexpr DiscreteElement< QueryDDims... > front(DiscreteDomain< DDims... > const &domain) noexcept
Definition: discrete_domain.hpp:249
constexpr auto select_by_type_seq(DiscreteDomain< DDims... > const &domain)
Definition: discrete_domain.hpp:299
constexpr DiscreteDomain< QueryDDims... > select(DiscreteDomain< DDims... > const &domain)
Definition: discrete_domain.hpp:235
ddc_detail::TaggedVector< CoordinateElement, CDims... > Coordinate
A Coordinate represents a coordinate in the continuous space.
Definition: coordinate.hpp:19
ddc::Coordinate< QueryDDims... > rmax(DiscreteDomain< DDims... > const &domain) noexcept
Definition: discrete_domain.hpp:276
constexpr DiscreteVectorElement const & get(DiscreteVector< Tags... > const &tuple) noexcept
Definition: discrete_vector.hpp:36
Definition: discrete_domain.hpp:306
constexpr friend bool operator!=(DiscreteDomainIterator const &xx, DiscreteDomainIterator const &yy)
Definition: discrete_domain.hpp:382
constexpr friend DiscreteDomainIterator operator+(difference_type __n, DiscreteDomainIterator __i)
Definition: discrete_domain.hpp:424
constexpr friend DiscreteDomainIterator operator+(DiscreteDomainIterator __i, difference_type __n)
Definition: discrete_domain.hpp:417
constexpr friend bool operator<(DiscreteDomainIterator const &xx, DiscreteDomainIterator const &yy)
Definition: discrete_domain.hpp:389
constexpr DiscreteDomainIterator & operator-=(difference_type __n)
Definition: discrete_domain.hpp:361
constexpr DiscreteDomainIterator operator++(int)
Definition: discrete_domain.hpp:332
constexpr DiscreteDomainIterator(DiscreteElement< DDim > __value)
Definition: discrete_domain.hpp:319
constexpr DiscreteDomainIterator & operator++()
Definition: discrete_domain.hpp:326
constexpr friend bool operator==(DiscreteDomainIterator const &xx, DiscreteDomainIterator const &yy)
Definition: discrete_domain.hpp:375
constexpr DiscreteElement< DDim > operator*() const noexcept
Definition: discrete_domain.hpp:321
constexpr friend difference_type operator-(DiscreteDomainIterator const &xx, DiscreteDomainIterator const &yy)
Definition: discrete_domain.hpp:438
constexpr friend DiscreteDomainIterator operator-(DiscreteDomainIterator __i, difference_type __n)
Definition: discrete_domain.hpp:431
constexpr DiscreteDomainIterator operator--(int)
Definition: discrete_domain.hpp:345
constexpr DiscreteElement< DDim > operator[](difference_type __n) const
Definition: discrete_domain.hpp:370
constexpr friend bool operator>=(DiscreteDomainIterator const &xx, DiscreteDomainIterator const &yy)
Definition: discrete_domain.hpp:410
std::ptrdiff_t difference_type
Definition: discrete_domain.hpp:315
constexpr friend bool operator>(DiscreteDomainIterator const &xx, DiscreteDomainIterator const &yy)
Definition: discrete_domain.hpp:396
std::random_access_iterator_tag iterator_category
Definition: discrete_domain.hpp:311
constexpr friend bool operator<=(DiscreteDomainIterator const &xx, DiscreteDomainIterator const &yy)
Definition: discrete_domain.hpp:403
constexpr DiscreteDomainIterator & operator--()
Definition: discrete_domain.hpp:339
constexpr DiscreteDomainIterator & operator+=(difference_type __n)
Definition: discrete_domain.hpp:352
static constexpr auto select(Domain const &domain)
Definition: discrete_domain.hpp:290