alpaka
Abstraction Library for Parallel Kernel Acceleration
Vec.hpp
Go to the documentation of this file.
1 /* Copyright 2023 Axel Huebl, Benjamin Worpitz, Erik Zenker, Matthias Werner, RenĂ© Widera, Andrea Bocci, Jan Stephan,
2  * Bernhard Manfred Gruber
3  * SPDX-License-Identifier: MPL-2.0
4  */
5 
6 #pragma once
7 
8 #include "alpaka/core/Align.hpp"
9 #include "alpaka/core/Assert.hpp"
11 #include "alpaka/core/Common.hpp"
14 #include "alpaka/dim/Traits.hpp"
15 #include "alpaka/idx/Traits.hpp"
16 #include "alpaka/meta/Fold.hpp"
19 #include "alpaka/vec/Traits.hpp"
20 
21 #include <algorithm>
22 #include <cstdint>
23 #include <functional>
24 #include <limits>
25 #include <ostream>
26 #include <tuple>
27 #include <type_traits>
28 #include <utility>
29 
30 namespace alpaka
31 {
32  template<typename TDim, typename TVal>
33  class Vec;
34 
35  //! A n-dimensional vector.
36  template<typename TDim, typename TVal>
37  class Vec final
38  {
39  public:
40  static_assert(TDim::value >= 0u, "Invalid dimensionality");
41 
42  using Dim = TDim;
43  using Val = TVal;
44  using value_type = Val; //!< STL-like value_type.
45 
46  private:
47  //! A sequence of integers from 0 to dim-1.
48  //! This can be used to write compile time indexing algorithms.
49  using IdxSequence = std::make_integer_sequence<std::size_t, TDim::value>;
50 
51  public:
52  ALPAKA_FN_HOST_ACC constexpr Vec() : m_data{}
53  {
54  }
55 
56  //! Value constructor.
57  //! This constructor is only available if the number of parameters matches the vector idx.
59 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC >= BOOST_VERSION_NUMBER(11, 3, 0) \
60  && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 4, 0)
61  // This constructor tries to avoid SFINAE, which crashes nvcc 11.3. We also need to have a first
62  // argument, so an unconstrained ctor with forwarding references does not hijack the compiler provided
63  // copy-ctor.
64  template<typename... TArgs>
65  ALPAKA_FN_HOST_ACC constexpr Vec(TVal arg0, TArgs&&... args)
66  : m_data{std::move(arg0), static_cast<TVal>(std::forward<TArgs>(args))...}
67  {
68  static_assert(
69  1 + sizeof...(TArgs) == TDim::value && (std::is_convertible_v<std::decay_t<TArgs>, TVal> && ...),
70  "Wrong number of arguments to Vec constructor or types are not convertible to TVal.");
71  }
72 #else
73  template<
74  typename... TArgs,
75  typename = std::enable_if_t<
76  sizeof...(TArgs) == TDim::value && (std::is_convertible_v<std::decay_t<TArgs>, TVal> && ...)>>
77  ALPAKA_FN_HOST_ACC constexpr Vec(TArgs&&... args) : m_data{static_cast<TVal>(std::forward<TArgs>(args))...}
78  {
79  }
80 #endif
81 
82  //! Generator constructor.
83  //! Initializes the vector with the values returned from generator(IC) in order, where IC::value runs from 0 to
84  //! TDim - 1 (inclusive).
85 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC >= BOOST_VERSION_NUMBER(11, 3, 0) \
86  && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 4, 0)
87  template<typename F>
88  ALPAKA_FN_HOST_ACC constexpr explicit Vec(
89  F&& generator,
90  std::void_t<decltype(generator(std::integral_constant<std::size_t, 0>{}))>* ignore = nullptr)
91  : Vec(std::forward<F>(generator), std::make_index_sequence<TDim::value>{})
92  {
93  static_cast<void>(ignore);
94  }
95 #else
96  template<typename F, std::enable_if_t<std::is_invocable_v<F, std::integral_constant<std::size_t, 0>>, int> = 0>
97  ALPAKA_FN_HOST_ACC constexpr explicit Vec(F&& generator)
98  : Vec(std::forward<F>(generator), std::make_index_sequence<TDim::value>{})
99  {
100  }
101 #endif
102 
103  private:
104  template<typename F, std::size_t... Is>
105  ALPAKA_FN_HOST_ACC constexpr explicit Vec(F&& generator, std::index_sequence<Is...>)
106  : m_data{generator(std::integral_constant<std::size_t, Is>{})...}
107  {
108  }
109 
110  public:
111  //! \brief Single value constructor.
112  //!
113  //! Creates a vector with all values set to val.
114  //! \param val The initial value.
116  ALPAKA_FN_HOST_ACC static constexpr auto all(TVal const& val) -> Vec<TDim, TVal>
117  {
118  Vec<TDim, TVal> v;
119  for(auto& e : v)
120  e = val;
121  return v;
122  }
123 
124  //! Zero value constructor.
126  ALPAKA_FN_HOST_ACC static constexpr auto zeros() -> Vec<TDim, TVal>
127  {
128  return all(static_cast<TVal>(0));
129  }
130 
131  //! One value constructor.
133  ALPAKA_FN_HOST_ACC static constexpr auto ones() -> Vec<TDim, TVal>
134  {
135  return all(static_cast<TVal>(1));
136  }
137 
138  ALPAKA_FN_HOST_ACC constexpr auto begin() -> TVal*
139  {
140  return m_data;
141  }
142 
143  ALPAKA_FN_HOST_ACC constexpr auto begin() const -> TVal const*
144  {
145  return m_data;
146  }
147 
148  ALPAKA_FN_HOST_ACC constexpr auto end() -> TVal*
149  {
150  return m_data + TDim::value;
151  }
152 
153  ALPAKA_FN_HOST_ACC constexpr auto end() const -> TVal const*
154  {
155  return m_data + TDim::value;
156  }
157 
158  ALPAKA_FN_HOST_ACC constexpr auto front() -> TVal&
159  {
160  return m_data[0];
161  }
162 
163  ALPAKA_FN_HOST_ACC constexpr auto front() const -> TVal const&
164  {
165  return m_data[0];
166  }
167 
168  ALPAKA_FN_HOST_ACC constexpr auto back() -> TVal&
169  {
170  return m_data[Dim::value - 1];
171  }
172 
173  ALPAKA_FN_HOST_ACC constexpr auto back() const -> TVal const&
174  {
175  return m_data[Dim::value - 1];
176  }
177 
178  //! access elements by name
179  //!
180  //! names: x,y,z,w
181  //! @{
182  template<typename TDefer = Dim, std::enable_if_t<std::is_same_v<TDefer, Dim> && Dim::value >= 1, int> = 0>
183  ALPAKA_FN_HOST_ACC constexpr decltype(auto) x() const
184  {
185  return m_data[Dim::value - 1];
186  }
187 
188  template<typename TDefer = Dim, std::enable_if_t<std::is_same_v<TDefer, Dim> && Dim::value >= 1, int> = 0>
189  ALPAKA_FN_HOST_ACC constexpr decltype(auto) x()
190  {
191  return m_data[Dim::value - 1];
192  }
193 
194  template<typename TDefer = Dim, std::enable_if_t<std::is_same_v<TDefer, Dim> && Dim::value >= 2, int> = 0>
195  ALPAKA_FN_HOST_ACC constexpr decltype(auto) y() const
196  {
197  return m_data[Dim::value - 2];
198  }
199 
200  template<typename TDefer = Dim, std::enable_if_t<std::is_same_v<TDefer, Dim> && Dim::value >= 2, int> = 0>
201  ALPAKA_FN_HOST_ACC constexpr decltype(auto) y()
202  {
203  return m_data[Dim::value - 2];
204  }
205 
206  template<typename TDefer = Dim, std::enable_if_t<std::is_same_v<TDefer, Dim> && Dim::value >= 3, int> = 0>
207  ALPAKA_FN_HOST_ACC constexpr decltype(auto) z() const
208  {
209  return m_data[Dim::value - 3];
210  }
211 
212  template<typename TDefer = Dim, std::enable_if_t<std::is_same_v<TDefer, Dim> && Dim::value >= 3, int> = 0>
213  ALPAKA_FN_HOST_ACC constexpr decltype(auto) z()
214  {
215  return m_data[Dim::value - 3];
216  }
217 
218  template<typename TDefer = Dim, std::enable_if_t<std::is_same_v<TDefer, Dim> && Dim::value >= 4, int> = 0>
219  ALPAKA_FN_HOST_ACC constexpr decltype(auto) w() const
220  {
221  return m_data[Dim::value - 4];
222  }
223 
224  template<typename TDefer = Dim, std::enable_if_t<std::is_same_v<TDefer, Dim> && Dim::value >= 4, int> = 0>
225  ALPAKA_FN_HOST_ACC constexpr decltype(auto) w()
226  {
227  return m_data[Dim::value - 4];
228  }
229 
230  //! @}
231 
232  //! Value reference accessor at the given non-unsigned integer index.
233  //! \return A reference to the value at the given index.
235  template<typename TIdx, typename = std::enable_if_t<std::is_integral_v<TIdx>>>
236  ALPAKA_FN_HOST_ACC constexpr auto operator[](TIdx const iIdx) -> TVal&
237  {
239  auto const idx = static_cast<typename TDim::value_type>(iIdx);
240  core::assertGreaterThan<TDim>(idx);
241  return m_data[idx];
242  }
243 
244  //! Value accessor at the given non-unsigned integer index.
245  //! \return The value at the given index.
247  template<typename TIdx, typename = std::enable_if_t<std::is_integral_v<TIdx>>>
248  ALPAKA_FN_HOST_ACC constexpr auto operator[](TIdx const iIdx) const -> TVal
249  {
251  auto const idx = static_cast<typename TDim::value_type>(iIdx);
252  core::assertGreaterThan<TDim>(idx);
253  return m_data[idx];
254  }
255 
257  template<typename TFnObj, std::size_t... TIndices>
258  [[nodiscard]] ALPAKA_FN_HOST_ACC constexpr auto foldrByIndices(
259  TFnObj const& f,
260  std::integer_sequence<std::size_t, TIndices...>) const
261  {
262  return meta::foldr(f, (*this)[TIndices]...);
263  }
264 
266  template<typename TFnObj, std::size_t... TIndices>
267  [[nodiscard]] ALPAKA_FN_HOST_ACC constexpr auto foldrByIndices(
268  TFnObj const& f,
269  std::integer_sequence<std::size_t, TIndices...>,
270  TVal initial) const
271  {
272  return meta::foldr(f, (*this)[TIndices]..., initial);
273  }
274 
276  template<typename TFnObj>
277  [[nodiscard]] ALPAKA_FN_HOST_ACC constexpr auto foldrAll(TFnObj const& f) const
278  {
279  return foldrByIndices(f, IdxSequence());
280  }
281 
283  template<typename TFnObj>
284  [[nodiscard]] ALPAKA_FN_HOST_ACC constexpr auto foldrAll(TFnObj const& f, TVal initial) const
285  {
286  return foldrByIndices(f, IdxSequence(), initial);
287  }
288 
289 // suppress strange warning produced by nvcc+MSVC in release mode
290 #if BOOST_COMP_MSVC || defined(BOOST_COMP_MSVC_EMULATED)
291 # pragma warning(push)
292 # pragma warning(disable : 4702) // unreachable code
293 #endif
294  //! \return The product of all values.
296  [[nodiscard]] ALPAKA_FN_HOST_ACC constexpr auto prod() const -> TVal
297  {
298  return foldrAll(std::multiplies<TVal>{}, TVal{1});
299  }
300 #if BOOST_COMP_MSVC || defined(BOOST_COMP_MSVC_EMULATED)
301 # pragma warning(pop)
302 #endif
303  //! \return The sum of all values.
305  [[nodiscard]] ALPAKA_FN_HOST_ACC constexpr auto sum() const -> TVal
306  {
307  return foldrAll(std::plus<TVal>{}, TVal{0});
308  }
309 
310  //! \return The min of all values.
312  [[nodiscard]] ALPAKA_FN_HOST_ACC constexpr auto min() const -> TVal
313  {
314  return foldrAll(meta::min<TVal>{}, std::numeric_limits<TVal>::max());
315  }
316 
317  //! \return The max of all values.
319  [[nodiscard]] ALPAKA_FN_HOST_ACC constexpr auto max() const -> TVal
320  {
321  return foldrAll(meta::max<TVal>{}, std::numeric_limits<TVal>::min());
322  }
323 
324  //! \return True if all values are true, i.e., the "logical and" of all values.
326  [[nodiscard]] ALPAKA_FN_HOST_ACC constexpr auto all() const -> bool
327  {
328  return foldrAll(std::logical_and<TVal>{}, true);
329  }
330 
331  //! \return True if any value is true, i.e., the "logical or" of all values.
333  [[nodiscard]] ALPAKA_FN_HOST_ACC constexpr auto any() const -> bool
334  {
335  return foldrAll(std::logical_or<TVal>{}, false);
336  }
337 
338  //! \return True if none of the values are true
340  [[nodiscard]] ALPAKA_FN_HOST_ACC constexpr auto none() const -> bool
341  {
342  return !foldrAll(std::logical_or<TVal>{}, false);
343  }
344 
345  //! \return The index of the minimal element.
346  [[nodiscard]] ALPAKA_FN_HOST constexpr auto minElem() const -> typename TDim::value_type
347  {
348  return static_cast<typename TDim::value_type>(
349  std::distance(std::begin(m_data), std::min_element(std::begin(m_data), std::end(m_data))));
350  }
351 
352  //! \return The index of the maximal element.
353  [[nodiscard]] ALPAKA_FN_HOST constexpr auto maxElem() const -> typename TDim::value_type
354  {
355  return static_cast<typename TDim::value_type>(
356  std::distance(std::begin(m_data), std::max_element(std::begin(m_data), std::end(m_data))));
357  }
358 
359  template<size_t I>
360  ALPAKA_FN_HOST_ACC constexpr auto get() -> TVal&
361  {
362  return (*this)[I];
363  }
364 
365  template<size_t I>
366  [[nodiscard]] ALPAKA_FN_HOST_ACC constexpr auto get() const -> TVal
367  {
368  return (*this)[I];
369  }
370 
371  //! \return The number of dimensions of the vector.
372  [[nodiscard]] ALPAKA_FN_HOST_ACC static consteval auto dim() noexcept -> TVal
373  {
374  return TDim::value;
375  }
376 
377  //! \return The element-wise sum of two vectors.
379  ALPAKA_FN_HOST_ACC friend constexpr auto operator+(Vec const& p, Vec const& q) -> Vec
380  {
381  Vec r;
382 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
383  if(TDim::value > 0)
384 #else
385  if constexpr(TDim::value > 0)
386 #endif
387  {
388  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
389  r[i] = p[i] + q[i];
390  }
391  return r;
392  }
393 
394  //! \return The element-wise difference of two vectors.
396  ALPAKA_FN_HOST_ACC friend constexpr auto operator-(Vec const& p, Vec const& q) -> Vec
397  {
398  Vec r;
399 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
400  if(TDim::value > 0)
401 #else
402  if constexpr(TDim::value > 0)
403 #endif
404  {
405 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
406 # pragma diag_suppress = unsigned_compare_with_zero
407 #endif
408  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
409 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
410 # pragma diag_default = unsigned_compare_with_zero
411 #endif
412  r[i] = p[i] - q[i];
413  }
414  return r;
415  }
416 
417  //! \return The element-wise product of two vectors.
419  ALPAKA_FN_HOST_ACC friend constexpr auto operator*(Vec const& p, Vec const& q) -> Vec
420  {
421  Vec r;
422 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
423  if(TDim::value > 0)
424 #else
425  if constexpr(TDim::value > 0)
426 #endif
427  {
428  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
429  r[i] = p[i] * q[i];
430  }
431  return r;
432  }
433 
435  ALPAKA_FN_HOST_ACC friend constexpr auto operator==(Vec const& a, Vec const& b) -> bool
436  {
437 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
438  if(TDim::value > 0)
439 #else
440  if constexpr(TDim::value > 0)
441 #endif
442  {
443 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
444 # pragma diag_suppress = unsigned_compare_with_zero
445 #endif
446  for(typename TDim::value_type i(0); i < TDim::value; ++i)
447 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
448 # pragma diag_default = unsigned_compare_with_zero
449 #endif
450  {
451  if(a[i] != b[i])
452  return false;
453  }
454  }
455  return true;
456  }
457 
459  ALPAKA_FN_HOST_ACC friend constexpr auto operator!=(Vec const& a, Vec const& b) -> bool
460  {
461  return !(a == b);
462  }
463 
464  //! \return The element-wise less than relation of two vectors.
466  ALPAKA_FN_HOST_ACC friend constexpr auto operator<(Vec const& p, Vec const& q) -> Vec<TDim, bool>
467  {
468  Vec<TDim, bool> r;
469 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
470  if(TDim::value > 0)
471 #else
472  if constexpr(TDim::value > 0)
473 #endif
474  {
475  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
476  r[i] = p[i] < q[i];
477  }
478  return r;
479  }
480 
481  //! \return The element-wise less than relation of two vectors.
483  ALPAKA_FN_HOST_ACC friend constexpr auto operator<=(Vec const& p, Vec const& q) -> Vec<TDim, bool>
484  {
485  Vec<TDim, bool> r;
486 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
487  if(TDim::value > 0)
488 #else
489  if constexpr(TDim::value > 0)
490 #endif
491  {
492  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
493  r[i] = p[i] <= q[i];
494  }
495  return r;
496  }
497 
498  //! \return The element-wise greater than relation of two vectors.
500  ALPAKA_FN_HOST_ACC friend constexpr auto operator>(Vec const& p, Vec const& q) -> Vec<TDim, bool>
501  {
502  Vec<TDim, bool> r;
503 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
504  if(TDim::value > 0)
505 #else
506  if constexpr(TDim::value > 0)
507 #endif
508  {
509  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
510  r[i] = p[i] > q[i];
511  }
512  return r;
513  }
514 
515  //! \return The element-wise greater equal than relation of two vectors.
517  ALPAKA_FN_HOST_ACC friend constexpr auto operator>=(Vec const& p, Vec const& q) -> Vec<TDim, bool>
518  {
519  Vec<TDim, bool> r;
520 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
521  if(TDim::value > 0)
522 #else
523  if constexpr(TDim::value > 0)
524 #endif
525  {
526  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
527  r[i] = p[i] >= q[i];
528  }
529  return r;
530  }
531 
532  //! \return The element-wise logical and relation of two vectors.
534  ALPAKA_FN_HOST_ACC friend constexpr auto operator&&(Vec const& p, Vec const& q) -> Vec<TDim, bool>
535  {
536  Vec<TDim, bool> r;
537 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
538  if(TDim::value > 0)
539 #else
540  if constexpr(TDim::value > 0)
541 #endif
542  {
543  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
544  r[i] = p[i] && q[i];
545  }
546  return r;
547  }
548 
549  //! \return The element-wise logical or relation of two vectors.
551  ALPAKA_FN_HOST_ACC friend constexpr auto operator||(Vec const& p, Vec const& q) -> Vec<TDim, bool>
552  {
553  Vec<TDim, bool> r;
554 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
555  if(TDim::value > 0)
556 #else
557  if constexpr(TDim::value > 0)
558 #endif
559  {
560  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
561  r[i] = p[i] || q[i];
562  }
563  return r;
564  }
565 
566  ALPAKA_FN_HOST friend constexpr auto operator<<(std::ostream& os, Vec const& v) -> std::ostream&
567  {
568  os << "(";
569 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
570  if(TDim::value > 0)
571 #else
572  if constexpr(TDim::value > 0)
573 #endif
574  {
575 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
576 # pragma diag_suppress = unsigned_compare_with_zero
577 #endif
578  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
579 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
580 # pragma diag_default = unsigned_compare_with_zero
581 #endif
582  {
583  os << v[i];
584  if(i != TDim::value - 1)
585  os << ", ";
586  }
587  }
588  else
589  os << ".";
590  os << ")";
591 
592  return os;
593  }
594 
595  private:
596  // Zero sized arrays are not allowed, therefore zero-dimensional vectors have one member.
597  TVal m_data[TDim::value == 0u ? 1u : TDim::value];
598  };
599 
600  template<typename TFirstIndex, typename... TRestIndices>
601  ALPAKA_FN_HOST_ACC Vec(TFirstIndex&&, TRestIndices&&...)
602  -> Vec<DimInt<1 + sizeof...(TRestIndices)>, std::decay_t<TFirstIndex>>;
603 
604  template<typename T>
605  inline constexpr bool isVec = false;
606 
607  template<typename TDim, typename TVal>
608  inline constexpr bool isVec<Vec<TDim, TVal>> = true;
609 
610  //! Converts a Vec to a std::array
611  template<typename TDim, typename TVal>
612  ALPAKA_FN_HOST_ACC constexpr auto toArray(Vec<TDim, TVal> const& v) -> std::array<TVal, TDim::value>
613  {
614  std::array<TVal, TDim::value> a{};
615 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
616  if(TDim::value > 0)
617 #else
618  if constexpr(TDim::value > 0)
619 #endif
620  {
621  for(unsigned i = 0; i < TDim::value; i++)
622  a[i] = v[i];
623  }
624  return a;
625  }
626 
627  //! \return The element-wise minimum of one or more vectors.
629  template<
630  typename TDim,
631  typename TVal,
632  typename... Vecs,
633  typename = std::enable_if_t<(std::is_same_v<Vec<TDim, TVal>, Vecs> && ...)>>
634  ALPAKA_FN_HOST_ACC constexpr auto elementwise_min(Vec<TDim, TVal> const& p, Vecs const&... qs) -> Vec<TDim, TVal>
635  {
636  Vec<TDim, TVal> r;
637 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
638  if(TDim::value > 0)
639 #else
640  if constexpr(TDim::value > 0)
641 #endif
642  {
643  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
644  r[i] = std::min({p[i], qs[i]...});
645  }
646  return r;
647  }
648 
649  //! \return The element-wise maximum of one or more vectors.
651  template<
652  typename TDim,
653  typename TVal,
654  typename... Vecs,
655  typename = std::enable_if_t<(std::is_same_v<Vec<TDim, TVal>, Vecs> && ...)>>
656  ALPAKA_FN_HOST_ACC constexpr auto elementwise_max(Vec<TDim, TVal> const& p, Vecs const&... qs) -> Vec<TDim, TVal>
657  {
658  Vec<TDim, TVal> r;
659 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
660  if(TDim::value > 0)
661 #else
662  if constexpr(TDim::value > 0)
663 #endif
664  {
665  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
666  r[i] = std::max({p[i], qs[i]...});
667  }
668  return r;
669  }
670 
671  namespace trait
672  {
673  //! The Vec dimension get trait specialization.
674  template<typename TDim, typename TVal>
675  struct DimType<Vec<TDim, TVal>>
676  {
677  using type = TDim;
678  };
679 
680  //! The Vec idx type trait specialization.
681  template<typename TDim, typename TVal>
682  struct IdxType<Vec<TDim, TVal>>
683  {
684  using type = TVal;
685  };
686 
687  //! Specialization for selecting a sub-vector.
688  template<typename TDim, typename TVal, std::size_t... TIndices>
689  struct SubVecFromIndices<Vec<TDim, TVal>, std::index_sequence<TIndices...>>
690  {
692  Vec<TDim, TVal> const& vec) -> Vec<DimInt<sizeof...(TIndices)>, TVal>
693  {
694  if constexpr(std::is_same_v<std::index_sequence<TIndices...>, std::make_index_sequence<TDim::value>>)
695  {
696  return vec; // Return whole vector.
697  }
698  else
699  {
700  static_assert(
701  sizeof...(TIndices) <= TDim::value,
702  "The sub-vector's dimensionality must be smaller than or equal to the original "
703  "dimensionality.");
704  return {vec[TIndices]...}; // Return sub-vector.
705  }
706  ALPAKA_UNREACHABLE({});
707  }
708  };
709 
710  template<typename TValNew, typename TDim, typename TVal>
711  struct CastVec<TValNew, Vec<TDim, TVal>>
712  {
714  ALPAKA_FN_HOST_ACC static constexpr auto castVec(Vec<TDim, TVal> const& vec) -> Vec<TDim, TValNew>
715  {
716  if constexpr(std::is_same_v<TValNew, TVal>)
717  {
718  return vec;
719  }
720  else
721  {
723 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
724  if(TDim::value > 0)
725 #else
726  if constexpr(TDim::value > 0)
727 #endif
728  {
729  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
730  r[i] = static_cast<TValNew>(vec[i]);
731  }
732  return r;
733  }
734  ALPAKA_UNREACHABLE({});
735  }
736  };
737 
738  //! ReverseVec specialization for Vec.
739  template<typename TDim, typename TVal>
740  struct ReverseVec<Vec<TDim, TVal>>
741  {
743  ALPAKA_FN_HOST_ACC static constexpr auto reverseVec(Vec<TDim, TVal> const& vec) -> Vec<TDim, TVal>
744  {
745  if constexpr(TDim::value <= 1)
746  {
747  return vec;
748  }
749  else
750  {
751  Vec<TDim, TVal> r;
752  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
753  r[i] = vec[TDim::value - 1u - i];
754  return r;
755  }
756  ALPAKA_UNREACHABLE({});
757  }
758  };
759 
760  //! Concatenation specialization for Vec.
761  template<typename TDimL, typename TDimR, typename TVal>
762  struct ConcatVec<Vec<TDimL, TVal>, Vec<TDimR, TVal>>
763  {
765  ALPAKA_FN_HOST_ACC static constexpr auto concatVec(
766  Vec<TDimL, TVal> const& vecL,
768  {
770  if constexpr(TDimL::value > 0)
771  {
772  for(typename TDimL::value_type i = 0; i < TDimL::value; ++i)
773  r[i] = vecL[i];
774  }
775  if constexpr(TDimR::value > 0)
776  {
777  for(typename TDimR::value_type i = 0; i < TDimR::value; ++i)
778  r[TDimL::value + i] = vecR[i];
779  }
780  return r;
781  }
782  };
783  } // namespace trait
784 } // namespace alpaka
785 
786 #if defined(__clang__)
787 # pragma GCC diagnostic push
788 # pragma GCC diagnostic ignored "-Wmismatched-tags"
789 #endif
790 namespace std
791 {
792  template<typename TDim, typename TVal>
793  struct tuple_size<alpaka::Vec<TDim, TVal>> : integral_constant<size_t, TDim::value>
794  {
795  };
796 
797  template<size_t I, typename TDim, typename TVal>
798  struct tuple_element<I, alpaka::Vec<TDim, TVal>>
799  {
800  using type = TVal;
801  };
802 } // namespace std
803 #if defined(__clang__)
804 # pragma GCC diagnostic pop
805 #endif
#define ALPAKA_UNREACHABLE(...)
Before CUDA 11.5 nvcc is unable to correctly identify return statements in 'if constexpr' branches....
Definition: Unreachable.hpp:24
A n-dimensional vector.
Definition: Vec.hpp:38
constexpr ALPAKA_FN_HOST_ACC auto front() const -> TVal const &
Definition: Vec.hpp:163
ALPAKA_NO_HOST_ACC_WARNING static constexpr ALPAKA_FN_HOST_ACC auto ones() -> Vec< TDim, TVal >
One value constructor.
Definition: Vec.hpp:133
constexpr ALPAKA_FN_HOST_ACC auto back() const -> TVal const &
Definition: Vec.hpp:173
constexpr ALPAKA_FN_HOST_ACC auto begin() -> TVal *
Definition: Vec.hpp:138
ALPAKA_NO_HOST_ACC_WARNING static constexpr ALPAKA_FN_HOST_ACC auto all(TVal const &val) -> Vec< TDim, TVal >
Single value constructor.
Definition: Vec.hpp:116
Val value_type
STL-like value_type.
Definition: Vec.hpp:44
constexpr ALPAKA_FN_HOST_ACC auto end() -> TVal *
Definition: Vec.hpp:148
ALPAKA_NO_HOST_ACC_WARNING static constexpr ALPAKA_FN_HOST_ACC auto zeros() -> Vec< TDim, TVal >
Zero value constructor.
Definition: Vec.hpp:126
TDim Dim
Definition: Vec.hpp:42
constexpr ALPAKA_FN_HOST_ACC auto end() const -> TVal const *
Definition: Vec.hpp:153
ALPAKA_NO_HOST_ACC_WARNING constexpr ALPAKA_FN_HOST_ACC Vec(TArgs &&... args)
Value constructor. This constructor is only available if the number of parameters matches the vector ...
Definition: Vec.hpp:77
constexpr ALPAKA_FN_HOST_ACC auto front() -> TVal &
Definition: Vec.hpp:158
TVal Val
Definition: Vec.hpp:43
constexpr ALPAKA_FN_HOST_ACC Vec()
Definition: Vec.hpp:52
constexpr ALPAKA_FN_HOST_ACC Vec(F &&generator)
Generator constructor. Initializes the vector with the values returned from generator(IC) in order,...
Definition: Vec.hpp:97
constexpr ALPAKA_FN_HOST_ACC auto back() -> TVal &
Definition: Vec.hpp:168
constexpr ALPAKA_FN_HOST_ACC auto begin() const -> TVal const *
Definition: Vec.hpp:143
#define ALPAKA_FN_HOST
Definition: Common.hpp:40
#define ALPAKA_FN_HOST_ACC
Definition: Common.hpp:39
#define ALPAKA_NO_HOST_ACC_WARNING
Disable nvcc warning: 'calling a host function from host device function.' Usage: ALPAKA_NO_HOST_ACC_...
Definition: Common.hpp:82
ALPAKA_NO_HOST_ACC_WARNING constexpr ALPAKA_FN_HOST_ACC auto assertValueUnsigned(TArg const &arg) -> void
This method checks integral values if they are greater or equal zero. The implementation prevents war...
Definition: Assert.hpp:77
constexpr ALPAKA_FN_HOST_ACC bool operator==(Complex< T > const &lhs, Complex< T > const &rhs)
Equality of two complex numbers.
Definition: Complex.hpp:292
std::basic_ostream< TChar, TTraits > & operator<<(std::basic_ostream< TChar, TTraits > &os, Complex< T > const &x)
Host-only output of a complex number.
Definition: Complex.hpp:343
ALPAKA_FN_HOST_ACC Complex< T > operator*(Complex< T > const &lhs, Complex< T > const &rhs)
Muptiplication of two complex numbers.
Definition: Complex.hpp:242
ALPAKA_FN_HOST_ACC Complex< T > operator+(Complex< T > const &val)
Host-device arithmetic operations matching std::complex<T>.
Definition: Complex.hpp:186
constexpr ALPAKA_FN_HOST_ACC bool operator!=(Complex< T > const &lhs, Complex< T > const &rhs)
Inequality of two complex numbers.
Definition: Complex.hpp:318
ALPAKA_FN_HOST_ACC Complex< T > operator-(Complex< T > const &val)
Unary minus.
Definition: Complex.hpp:193
constexpr double e
Definition: Traits.hpp:58
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto max(T const &max_ctx, Tx const &x, Ty const &y)
Returns the larger of two arguments. NaNs are treated as missing data (between a NaN and a numeric va...
Definition: Traits.hpp:1263
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto min(T const &min_ctx, Tx const &x, Ty const &y)
Returns the smaller of two arguments. NaNs are treated as missing data (between a NaN and a numeric v...
Definition: Traits.hpp:1280
ALPAKA_NO_HOST_ACC_WARNING constexpr ALPAKA_FN_HOST_ACC auto foldr(TFnObj const &, T const &t) -> T
Definition: Fold.hpp:13
ALPAKA_FN_HOST auto end(TView &view) -> Iterator< TView >
Definition: Iterator.hpp:139
ALPAKA_FN_HOST auto begin(TView &view) -> Iterator< TView >
Definition: Iterator.hpp:133
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto all(TWarp const &warp, std::int32_t predicate) -> std::int32_t
Evaluates predicate for all active threads of the warp and returns non-zero if and only if predicate ...
Definition: Traits.hpp:114
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_ACC auto any(TWarp const &warp, std::int32_t predicate) -> std::int32_t
Evaluates predicate for all active threads of the warp and returns non-zero if and only if predicate ...
Definition: Traits.hpp:137
The alpaka accelerator library.
ALPAKA_NO_HOST_ACC_WARNING constexpr ALPAKA_FN_HOST_ACC auto elementwise_max(Vec< TDim, TVal > const &p, Vecs const &... qs) -> Vec< TDim, TVal >
Definition: Vec.hpp:656
constexpr ALPAKA_FN_HOST_ACC auto toArray(Vec< TDim, TVal > const &v) -> std::array< TVal, TDim::value >
Converts a Vec to a std::array.
Definition: Vec.hpp:612
constexpr bool isVec
Definition: Vec.hpp:605
ALPAKA_NO_HOST_ACC_WARNING constexpr ALPAKA_FN_HOST_ACC auto elementwise_min(Vec< TDim, TVal > const &p, Vecs const &... qs) -> Vec< TDim, TVal >
Definition: Vec.hpp:634
ALPAKA_FN_HOST_ACC Vec(TFirstIndex &&, TRestIndices &&...) -> Vec< DimInt< 1+sizeof...(TRestIndices)>, std::decay_t< TFirstIndex >>
std::integral_constant< std::size_t, N > DimInt
ALPAKA_NO_HOST_ACC_WARNING static constexpr ALPAKA_FN_HOST_ACC auto castVec(Vec< TDim, TVal > const &vec) -> Vec< TDim, TValNew >
Definition: Vec.hpp:714
Trait for casting a vector.
Definition: Traits.hpp:26
ALPAKA_NO_HOST_ACC_WARNING static constexpr ALPAKA_FN_HOST_ACC auto concatVec(Vec< TDimL, TVal > const &vecL, Vec< TDimR, TVal > const &vecR) -> Vec< DimInt< TDimL::value+TDimR::value >, TVal >
Definition: Vec.hpp:765
Trait for concatenating two vectors.
Definition: Traits.hpp:34
The dimension getter type trait.
Definition: Traits.hpp:14
The idx type trait.
Definition: Traits.hpp:25
ALPAKA_NO_HOST_ACC_WARNING static constexpr ALPAKA_FN_HOST_ACC auto reverseVec(Vec< TDim, TVal > const &vec) -> Vec< TDim, TVal >
Definition: Vec.hpp:743
Trait for reversing a vector.
Definition: Traits.hpp:30
ALPAKA_NO_HOST_ACC_WARNING static constexpr ALPAKA_FN_HOST_ACC auto subVecFromIndices(Vec< TDim, TVal > const &vec) -> Vec< DimInt< sizeof...(TIndices)>, TVal >
Definition: Vec.hpp:691
Trait for selecting a sub-vector.
Definition: Traits.hpp:22