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 element-wise sum of two vectors.
373  ALPAKA_FN_HOST_ACC friend constexpr auto operator+(Vec const& p, Vec const& q) -> Vec
374  {
375  Vec r;
376 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
377  if(TDim::value > 0)
378 #else
379  if constexpr(TDim::value > 0)
380 #endif
381  {
382  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
383  r[i] = p[i] + q[i];
384  }
385  return r;
386  }
387 
388  //! \return The element-wise difference of two vectors.
390  ALPAKA_FN_HOST_ACC friend constexpr auto operator-(Vec const& p, Vec const& q) -> Vec
391  {
392  Vec r;
393 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
394  if(TDim::value > 0)
395 #else
396  if constexpr(TDim::value > 0)
397 #endif
398  {
399 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
400 # pragma diag_suppress = unsigned_compare_with_zero
401 #endif
402  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
403 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
404 # pragma diag_default = unsigned_compare_with_zero
405 #endif
406  r[i] = p[i] - q[i];
407  }
408  return r;
409  }
410 
411  //! \return The element-wise product of two vectors.
413  ALPAKA_FN_HOST_ACC friend constexpr auto operator*(Vec const& p, Vec const& q) -> Vec
414  {
415  Vec r;
416 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
417  if(TDim::value > 0)
418 #else
419  if constexpr(TDim::value > 0)
420 #endif
421  {
422  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
423  r[i] = p[i] * q[i];
424  }
425  return r;
426  }
427 
429  ALPAKA_FN_HOST_ACC friend constexpr auto operator==(Vec const& a, Vec const& b) -> bool
430  {
431 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
432  if(TDim::value > 0)
433 #else
434  if constexpr(TDim::value > 0)
435 #endif
436  {
437 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
438 # pragma diag_suppress = unsigned_compare_with_zero
439 #endif
440  for(typename TDim::value_type i(0); i < TDim::value; ++i)
441 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
442 # pragma diag_default = unsigned_compare_with_zero
443 #endif
444  {
445  if(a[i] != b[i])
446  return false;
447  }
448  }
449  return true;
450  }
451 
453  ALPAKA_FN_HOST_ACC friend constexpr auto operator!=(Vec const& a, Vec const& b) -> bool
454  {
455  return !(a == b);
456  }
457 
458  //! \return The element-wise less than relation of two vectors.
460  ALPAKA_FN_HOST_ACC friend constexpr auto operator<(Vec const& p, Vec const& q) -> Vec<TDim, bool>
461  {
462  Vec<TDim, bool> r;
463 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
464  if(TDim::value > 0)
465 #else
466  if constexpr(TDim::value > 0)
467 #endif
468  {
469  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
470  r[i] = p[i] < q[i];
471  }
472  return r;
473  }
474 
475  //! \return The element-wise less than relation of two vectors.
477  ALPAKA_FN_HOST_ACC friend constexpr auto operator<=(Vec const& p, Vec const& q) -> Vec<TDim, bool>
478  {
479  Vec<TDim, bool> r;
480 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
481  if(TDim::value > 0)
482 #else
483  if constexpr(TDim::value > 0)
484 #endif
485  {
486  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
487  r[i] = p[i] <= q[i];
488  }
489  return r;
490  }
491 
492  //! \return The element-wise greater than relation of two vectors.
494  ALPAKA_FN_HOST_ACC friend constexpr auto operator>(Vec const& p, Vec const& q) -> Vec<TDim, bool>
495  {
496  Vec<TDim, bool> r;
497 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
498  if(TDim::value > 0)
499 #else
500  if constexpr(TDim::value > 0)
501 #endif
502  {
503  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
504  r[i] = p[i] > q[i];
505  }
506  return r;
507  }
508 
509  //! \return The element-wise greater equal than relation of two vectors.
511  ALPAKA_FN_HOST_ACC friend constexpr auto operator>=(Vec const& p, Vec const& q) -> Vec<TDim, bool>
512  {
513  Vec<TDim, bool> r;
514 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
515  if(TDim::value > 0)
516 #else
517  if constexpr(TDim::value > 0)
518 #endif
519  {
520  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
521  r[i] = p[i] >= q[i];
522  }
523  return r;
524  }
525 
526  //! \return The element-wise logical and relation of two vectors.
528  ALPAKA_FN_HOST_ACC friend constexpr auto operator&&(Vec const& p, Vec const& q) -> Vec<TDim, bool>
529  {
530  Vec<TDim, bool> r;
531 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
532  if(TDim::value > 0)
533 #else
534  if constexpr(TDim::value > 0)
535 #endif
536  {
537  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
538  r[i] = p[i] && q[i];
539  }
540  return r;
541  }
542 
543  //! \return The element-wise logical or relation of two vectors.
545  ALPAKA_FN_HOST_ACC friend constexpr auto operator||(Vec const& p, Vec const& q) -> Vec<TDim, bool>
546  {
547  Vec<TDim, bool> r;
548 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
549  if(TDim::value > 0)
550 #else
551  if constexpr(TDim::value > 0)
552 #endif
553  {
554  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
555  r[i] = p[i] || q[i];
556  }
557  return r;
558  }
559 
560  ALPAKA_FN_HOST friend constexpr auto operator<<(std::ostream& os, Vec const& v) -> std::ostream&
561  {
562  os << "(";
563 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
564  if(TDim::value > 0)
565 #else
566  if constexpr(TDim::value > 0)
567 #endif
568  {
569 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
570 # pragma diag_suppress = unsigned_compare_with_zero
571 #endif
572  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
573 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
574 # pragma diag_default = unsigned_compare_with_zero
575 #endif
576  {
577  os << v[i];
578  if(i != TDim::value - 1)
579  os << ", ";
580  }
581  }
582  else
583  os << ".";
584  os << ")";
585 
586  return os;
587  }
588 
589  private:
590  // Zero sized arrays are not allowed, therefore zero-dimensional vectors have one member.
591  TVal m_data[TDim::value == 0u ? 1u : TDim::value];
592  };
593 
594  template<typename TFirstIndex, typename... TRestIndices>
595  Vec(TFirstIndex&&, TRestIndices&&...) -> Vec<DimInt<1 + sizeof...(TRestIndices)>, std::decay_t<TFirstIndex>>;
596 
597  template<typename T>
598  inline constexpr bool isVec = false;
599 
600  template<typename TDim, typename TVal>
601  inline constexpr bool isVec<Vec<TDim, TVal>> = true;
602 
603  //! Converts a Vec to a std::array
604  template<typename TDim, typename TVal>
605  ALPAKA_FN_HOST_ACC constexpr auto toArray(Vec<TDim, TVal> const& v) -> std::array<TVal, TDim::value>
606  {
607  std::array<TVal, TDim::value> a{};
608 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
609  if(TDim::value > 0)
610 #else
611  if constexpr(TDim::value > 0)
612 #endif
613  {
614  for(unsigned i = 0; i < TDim::value; i++)
615  a[i] = v[i];
616  }
617  return a;
618  }
619 
620  //! \return The element-wise minimum of one or more vectors.
622  template<
623  typename TDim,
624  typename TVal,
625  typename... Vecs,
626  typename = std::enable_if_t<(std::is_same_v<Vec<TDim, TVal>, Vecs> && ...)>>
627  ALPAKA_FN_HOST_ACC constexpr auto elementwise_min(Vec<TDim, TVal> const& p, Vecs const&... qs) -> Vec<TDim, TVal>
628  {
629  Vec<TDim, TVal> r;
630 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
631  if(TDim::value > 0)
632 #else
633  if constexpr(TDim::value > 0)
634 #endif
635  {
636  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
637  r[i] = std::min({p[i], qs[i]...});
638  }
639  return r;
640  }
641 
642  //! \return The element-wise maximum of one or more vectors.
644  template<
645  typename TDim,
646  typename TVal,
647  typename... Vecs,
648  typename = std::enable_if_t<(std::is_same_v<Vec<TDim, TVal>, Vecs> && ...)>>
649  ALPAKA_FN_HOST_ACC constexpr auto elementwise_max(Vec<TDim, TVal> const& p, Vecs const&... qs) -> Vec<TDim, TVal>
650  {
651  Vec<TDim, TVal> r;
652 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
653  if(TDim::value > 0)
654 #else
655  if constexpr(TDim::value > 0)
656 #endif
657  {
658  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
659  r[i] = std::max({p[i], qs[i]...});
660  }
661  return r;
662  }
663 
664  namespace trait
665  {
666  //! The Vec dimension get trait specialization.
667  template<typename TDim, typename TVal>
668  struct DimType<Vec<TDim, TVal>>
669  {
670  using type = TDim;
671  };
672 
673  //! The Vec idx type trait specialization.
674  template<typename TDim, typename TVal>
675  struct IdxType<Vec<TDim, TVal>>
676  {
677  using type = TVal;
678  };
679 
680  //! Specialization for selecting a sub-vector.
681  template<typename TDim, typename TVal, std::size_t... TIndices>
682  struct SubVecFromIndices<Vec<TDim, TVal>, std::index_sequence<TIndices...>>
683  {
685  Vec<TDim, TVal> const& vec) -> Vec<DimInt<sizeof...(TIndices)>, TVal>
686  {
687  if constexpr(std::is_same_v<std::index_sequence<TIndices...>, std::make_index_sequence<TDim::value>>)
688  {
689  return vec; // Return whole vector.
690  }
691  else
692  {
693  static_assert(
694  sizeof...(TIndices) <= TDim::value,
695  "The sub-vector's dimensionality must be smaller than or equal to the original "
696  "dimensionality.");
697  return {vec[TIndices]...}; // Return sub-vector.
698  }
699  ALPAKA_UNREACHABLE({});
700  }
701  };
702 
703  template<typename TValNew, typename TDim, typename TVal>
704  struct CastVec<TValNew, Vec<TDim, TVal>>
705  {
707  ALPAKA_FN_HOST_ACC static constexpr auto castVec(Vec<TDim, TVal> const& vec) -> Vec<TDim, TValNew>
708  {
709  if constexpr(std::is_same_v<TValNew, TVal>)
710  {
711  return vec;
712  }
713  else
714  {
716 #if BOOST_COMP_NVCC && BOOST_COMP_NVCC < BOOST_VERSION_NUMBER(11, 3, 0)
717  if(TDim::value > 0)
718 #else
719  if constexpr(TDim::value > 0)
720 #endif
721  {
722  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
723  r[i] = static_cast<TValNew>(vec[i]);
724  }
725  return r;
726  }
727  ALPAKA_UNREACHABLE({});
728  }
729  };
730 
731  //! ReverseVec specialization for Vec.
732  template<typename TDim, typename TVal>
733  struct ReverseVec<Vec<TDim, TVal>>
734  {
736  ALPAKA_FN_HOST_ACC static constexpr auto reverseVec(Vec<TDim, TVal> const& vec) -> Vec<TDim, TVal>
737  {
738  if constexpr(TDim::value <= 1)
739  {
740  return vec;
741  }
742  else
743  {
744  Vec<TDim, TVal> r;
745  for(typename TDim::value_type i = 0; i < TDim::value; ++i)
746  r[i] = vec[TDim::value - 1u - i];
747  return r;
748  }
749  ALPAKA_UNREACHABLE({});
750  }
751  };
752 
753  //! Concatenation specialization for Vec.
754  template<typename TDimL, typename TDimR, typename TVal>
755  struct ConcatVec<Vec<TDimL, TVal>, Vec<TDimR, TVal>>
756  {
758  ALPAKA_FN_HOST_ACC static constexpr auto concatVec(
759  Vec<TDimL, TVal> const& vecL,
761  {
763  if constexpr(TDimL::value > 0)
764  {
765  for(typename TDimL::value_type i = 0; i < TDimL::value; ++i)
766  r[i] = vecL[i];
767  }
768  if constexpr(TDimR::value > 0)
769  {
770  for(typename TDimR::value_type i = 0; i < TDimR::value; ++i)
771  r[TDimL::value + i] = vecR[i];
772  }
773  return r;
774  }
775  };
776  } // namespace trait
777 } // namespace alpaka
778 
779 #if defined(__clang__)
780 # pragma GCC diagnostic push
781 # pragma GCC diagnostic ignored "-Wmismatched-tags"
782 #endif
783 namespace std
784 {
785  template<typename TDim, typename TVal>
786  struct tuple_size<alpaka::Vec<TDim, TVal>> : integral_constant<size_t, TDim::value>
787  {
788  };
789 
790  template<size_t I, typename TDim, typename TVal>
791  struct tuple_element<I, alpaka::Vec<TDim, TVal>>
792  {
793  using type = TVal;
794  };
795 } // namespace std
796 #if defined(__clang__)
797 # pragma GCC diagnostic pop
798 #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 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:649
ALPAKA_FN_HOST_ACC Complex< T > operator-(Complex< T > const &val)
Unary minus.
Definition: Complex.hpp:188
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:336
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:605
constexpr bool isVec
Definition: Vec.hpp:598
constexpr ALPAKA_FN_HOST_ACC bool operator==(Complex< T > const &lhs, Complex< T > const &rhs)
Equality of two complex numbers.
Definition: Complex.hpp:285
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:627
Vec(TFirstIndex &&, TRestIndices &&...) -> Vec< DimInt< 1+sizeof...(TRestIndices)>, std::decay_t< TFirstIndex >>
std::integral_constant< std::size_t, N > DimInt
ALPAKA_FN_HOST_ACC Complex< T > operator+(Complex< T > const &val)
Host-device arithmetic operations matching std::complex<T>.
Definition: Complex.hpp:181
constexpr ALPAKA_FN_HOST_ACC bool operator!=(Complex< T > const &lhs, Complex< T > const &rhs)
Inequality of two complex numbers.
Definition: Complex.hpp:311
ALPAKA_FN_HOST_ACC Complex< T > operator*(Complex< T > const &lhs, Complex< T > const &rhs)
Muptiplication of two complex numbers.
Definition: Complex.hpp:237
ALPAKA_NO_HOST_ACC_WARNING static constexpr ALPAKA_FN_HOST_ACC auto castVec(Vec< TDim, TVal > const &vec) -> Vec< TDim, TValNew >
Definition: Vec.hpp:707
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:758
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:736
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:684
Trait for selecting a sub-vector.
Definition: Traits.hpp:22