alpaka
Abstraction Library for Parallel Kernel Acceleration
Loading...
Searching...
No Matches
Simd.hpp
Go to the documentation of this file.
1/* Copyright 2025 René Widera
2 * SPDX-License-Identifier: MPL-2.0
3 */
4
5/** @file This file provides a basic implementation of a SIMD vector.
6 *
7 * The implementation is based on the class Vec:
8 * - the storge policy should become the native SIMD implementation e.g. std::simd
9 * - load/ store and simd specifis should be implemented in the storage policy
10 * - the name of storage policy should be changed
11 *
12 * The current operator operations relay on compilers auto vectorization.
13 */
14
15#pragma once
16
17#include "alpaka/SimdMask.hpp"
18#include "alpaka/Vec.hpp"
19#include "alpaka/cast.hpp"
20#include "alpaka/core/util.hpp"
23#include "alpaka/simd/trait.hpp"
24#include "alpaka/trait.hpp"
27
28#include <array>
29#include <bit>
30#include <concepts>
31#include <cstddef>
32#include <cstdint>
33#include <functional>
34#include <iosfwd>
35#include <ranges>
36#include <sstream>
37#include <string>
38#include <type_traits>
39
40namespace alpaka
41{
42 /** Simd vector
43 *
44 * @attention You should not use this type to create a buffer of SIMD vectors.
45 * The implementation is not ABI compatible between different API's.
46 * Using Simd data created on the host and used in the compute kernel will be undefined behaviour.
47 *
48 * This class is designed to be used via SimdPtr via reinterpretation of contiguous scalar data.
49 *
50 * @tparam T_Type data value type
51 * @tparam T_width number of lanes in the SIMD vector
52 * @tparam T_Storage wrapped native representation of the SIMD vector
53 */
54 template<
55 typename T_Type,
56 uint32_t T_width,
57 typename T_Storage =
58 /** do not use ALPAKA_TYPEOF(thisApi()) here else nvcc + gcc can trigger a compile error
59 * error: use of built-in trait '__remove_cv(alpaka::api::Host)' in function signature;
60 */
61 typename alpaka::trait::GetSimdStorageType<decltype(thisApi()), T_Type, T_width>::type>
62 struct Simd;
63
64 namespace trait
65 {
66 template<typename T_Type, uint32_t T_width, typename T_Storage>
68 {
69 };
70 } // namespace trait
71
72 // friend forward declaration
73 template<concepts::SimdMask T_Mask, concepts::Simd T_Simd>
74 struct SimdWhereExpr;
75
76 template<typename T_Type, uint32_t T_width, typename T_Storage>
77 struct Simd : private T_Storage
78 {
79 using Storage = T_Storage;
80 using type = typename T_Storage::value_type;
81 /** type is an implementation detail, can be a proxy type. */
82 using reference = typename T_Storage::reference;
83
84 using index_type = uint32_t;
85 using size_type = uint32_t;
86 using rank_type = uint32_t;
87
88 // universal vec used as fallback if T_Storage is holding the state in the template signature
90
91 /*Simds without elements are not allowed*/
92 static_assert(T_width > 0u);
93
94 constexpr Simd() = default;
95
96 using Storage::asNativeType;
97
98 /** static cast the instance to the storage type
99 *
100 * @attention: Do not use this method in user code, it is an implementation detail and can cause undefined
101 * behaviour if used wrong.
102 *
103 * @{
104 */
105 constexpr auto& asStorage()
106 {
107 return static_cast<Storage&>(*this);
108 }
109
110 constexpr auto const& asStorage() const
111 {
112 return static_cast<Storage const&>(*this);
113 }
114
115 /** @} */
116
117 /** Initialize via a generator expression
118 *
119 * The generator must return the value for the corresponding index of the component which is passed to the
120 * generator.
121 *
122 * This constructor is not constexpr because std::simd is using a reinterpret_cast during the initialization
123 * with a generator and complains that this is not allowed in constexpr functions.
124 */
125 template<
126 typename F,
127 std::enable_if_t<std::is_invocable_v<F, std::integral_constant<uint32_t, 0u>>, uint32_t> = 0u>
128 ALPAKA_FN_HOST_ACC explicit Simd(F&& generator)
129 : Simd(std::forward<F>(generator), std::make_integer_sequence<uint32_t, T_width>{})
130 {
131 /* Do not change the enable if to `requires(std::is_invocable_v<F, std::integral_constant<uint32_t, 0u>>)`
132 * nvcc 12.3.2 has a bug that creates compile issue when requires with std::is_invocable is used.
133 */
134 }
135
136 /** Constructor for SIMD pack
137 *
138 * @attention This constructor allows implicit casts.
139 *
140 * This constructor is not constexpr because std::simd is using a reinterpret_cast during the initialization
141 * with a generator and complains that this is not allowed in constexpr functions.
142 *
143 * @param args value of each lane index, x,y,z,...
144 *
145 */
146 template<typename... T_Args>
147 requires((std::is_convertible_v<T_Args, T_Type> && ...) && (sizeof...(T_Args) == T_width))
148 ALPAKA_FN_HOST_ACC Simd(T_Args const&... args) : Storage(static_cast<T_Type>(args)...)
149 {
150 }
151
152 constexpr Simd(Simd const& other) = default;
153
154 constexpr Simd(T_Storage const& other) : T_Storage{other}
155 {
156 }
157
158 /** constructor allows changing the storage policy
159 */
160 template<typename T_OtherStorage>
162 : Simd([&](uint32_t const i) constexpr { return other[i]; })
163 {
164 }
165
166 /** Allow static_cast / explicit cast to member type
167 *
168 * @attention only available for SIMD with a single lane.
169 */
170 constexpr explicit operator type() requires(T_width == 1u)
171 {
172 return (*this)[0];
173 }
174
175 /** Number of components/lanes in the SIMD pack. */
176 static consteval uint32_t width()
177 {
178 return T_width;
179 }
180
181 constexpr void copyFrom(T_Type const* data, concepts::Alignment auto alignment)
182 {
183 Storage::copyFrom(data, alignment);
184 }
185
186 constexpr void copyTo(auto* data, concepts::Alignment auto alignment) const
187 {
188 Storage::copyTo(data, alignment);
189 }
190
191 /**
192 * Creates a Simd where all lanes are set to the same value
193 *
194 * @param value Value which is set for all lanes
195 * @return new Simd<...>
196 */
197 static constexpr auto fill(concepts::Convertible<T_Type> auto value)
198 {
199 /* Note the function is taking value as copy because it is typically a scalar value.
200 * If a const reference is used, it would not be possible to pass a host defined constexpr value into
201 * fill() when CUDA is used. Issue was seen with nvcc CUDA 13.0.2. see
202 * https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#constexpr-variables
203 */
204 return Simd{Storage::fill(static_cast<T_Type>(value))};
205 }
206
207 constexpr Simd toRT() const
208 {
209 return *this;
210 }
211
212 constexpr Simd revert() const
213 {
214 Simd invertedSimd{};
215 for(uint32_t i = 0u; i < T_width; i++)
216 invertedSimd[T_width - 1 - i] = (*this)[i];
217
218 return invertedSimd;
219 }
220
221 constexpr Simd& operator=(Simd const&) = default;
222 constexpr Simd& operator=(Simd&&) = default;
223
224 constexpr Simd operator-() const
225 {
226 return Simd([this](uint32_t const i) constexpr { return -(*this)[i]; });
227 }
228
229 /** assign operator
230 * @{
231 */
232#define ALPAKA_VECTOR_ASSIGN_OP(op) \
233 template<typename T_OtherStorage> \
234 constexpr Simd& operator op(Simd<T_Type, T_width, T_OtherStorage> const& rhs) \
235 { \
236 this->asStorage() op rhs.asStorage(); \
237 return *this; \
238 } \
239 constexpr Simd& operator op(concepts::LosslesslyConvertible<T_Type> auto const value) \
240 { \
241 this->asStorage() op static_cast<T_Type>(value); \
242 return *this; \
243 }
244
250
251#undef ALPAKA_VECTOR_ASSIGN_OP
252
253 /** @} */
254
255 /** access a lane by index
256 *
257 * @return The returned type is implementation specific, therefore it can be a proxy reference.
258 * You can not use the returned value to deduct the type and assume that it will be the value type of
259 * Simd.
260 */
261 constexpr reference operator[](std::integral auto const idx)
262 {
263 return asStorage()[idx];
264 }
265
266 /** access a lane by index
267 *
268 * @return The value type, by copy.
269 */
270 constexpr type operator[](std::integral auto const idx) const
271 {
272 return asStorage()[idx];
273 }
274
275#define ALPAKA_NAMED_ARRAY_ACCESS(functionName, laneIdx) \
276 constexpr reference functionName() requires(T_width >= laneIdx + 1) \
277 { \
278 return (*this)[laneIdx]; \
279 } \
280 constexpr type functionName() const requires(T_width >= laneIdx + 1) \
281 { \
282 return (*this)[laneIdx]; \
283 }
284
285 /** @brief named lane access
286 *
287 * @attention The mapping from names x,y,z,w to memory indices differ from the mapping of an alpaka vector @c
288 * Vec. The availability of the naming methods depends on the SIMD width.
289 *
290 * You can have access to the same lane index via different nonspecific naming.
291 *
292 * @code
293 * lane index : 0, 1, 2, 3, ..., 9, 10, ... , 15
294 * hexadecimal : s0, s1, s2, s3, ..., s9, SA, ... , SF
295 * coordinate : x, y, z, w
296 * color channel: r, g, b, a
297 * @endcode
298 *
299 * @{
300 */
305
310
327 /** @} */
328
329#undef ALPAKA_NAMED_ARRAY_ACCESS
330
331 /** Shrink the number of elements of a vector.
332 *
333 * Highest indices kept alive.
334 *
335 * @tparam T_numElements New width of the SIMD pack.
336 * @return First T_numElements elements of the origin vector
337 */
338 template<uint32_t T_numElements>
340 {
341 static_assert(T_numElements <= T_width);
343 for(uint32_t i = 0u; i < T_numElements; i++)
344 result[T_numElements - 1u - i] = (*this)[T_width - 1u - i];
345
346 return result;
347 }
348
349 /** Shrink the SIMD pack
350 *
351 * Removes the last value.
352 */
353 constexpr Simd<T_Type, T_width - 1u> eraseBack() const requires(T_width > 1u)
354 {
355 constexpr auto reducedDim = T_width - 1u;
357 for(uint32_t i = 0u; i < reducedDim; i++)
358 result[i] = (*this)[i];
359
360 return result;
361 }
362
363 /** Shrink the number of elements of a vector.
364 *
365 * @tparam T_numElements New width of the SIMD pack.
366 * @param startIdx Index within the origin vector which will be the last element in the result.
367 * @return T_numElements elements of the origin vector starting with the index startIdx.
368 * Indexing will wrapp around when the begin of the origin vector is reached.
369 */
370 template<uint32_t T_numElements>
371 constexpr Simd<type, T_numElements> rshrink(std::integral auto const startIdx) const
372 {
373 static_assert(T_numElements <= T_width);
375 for(uint32_t i = 0u; i < T_numElements; i++)
376 result[T_numElements - 1u - i] = (*this)[(T_width + startIdx - i) % T_width];
377 return result;
378 }
379
380 /** Removes a component
381 *
382 * It is not allowed to call this method on a vector with the width of one.
383 *
384 * @tparam laneIdxToRemove index which shall be removed; range: [ 0; T_width - 1 ]
385 * @return vector with `T_width - 1` elements
386 */
387 template<std::integral auto laneIdxToRemove>
388 constexpr Simd<type, T_width - 1u> remove() const requires(T_width >= 2u)
389 {
390 Simd<type, T_width - 1u> result{};
391 for(int i = 0u; i < static_cast<int>(T_width - 1u); ++i)
392 {
393 // skip component which must be deleted
394 int const sourceIdx = i >= static_cast<int>(laneIdxToRemove) ? i + 1 : i;
395 result[i] = (*this)[sourceIdx];
396 }
397 return result;
398 }
399
400 /** Returns product of all components.
401 *
402 * @return product of components
403 */
404 [[nodiscard]] constexpr type product() const
405 {
406 return reduce(std::multiplies{});
407 }
408
409 /** Returns sum of all components.
410 *
411 * @return sum of components
412 */
413 [[nodiscard]] constexpr type sum() const
414 {
415 return reduce(std::plus{});
416 }
417
418 /** reduce all elements to a single value
419 *
420 * For better numerical stability a tree reduce algorithm is used.
421 *
422 * @tparam BinaryOp binary functor executed to reduce the range
423 * The binary operation must be associative.
424 * @return the type of the result depends on the binary functor
425 */
426 [[nodiscard]] constexpr auto reduce(auto&& reduceFunc) const
427 -> decltype(reduceFunc(std::declval<type>(), std::declval<type>()))
428 {
429 return reduce_range(ALPAKA_FORWARD(reduceFunc));
430 }
431
432 template<typename T_OtherStorage>
433 constexpr auto min(Simd<T_Type, T_width, T_OtherStorage> const& rhs) const
434 {
435 Simd result{};
436 for(uint32_t d = 0u; d < T_width; d++)
437 result[d] = std::min((*this)[d], rhs[d]);
438 return result;
439 }
440
441 /** create string out of the SIMD pack
442 *
443 * @param separator string to separate components of the SIMD pack
444 * @param enclosings string with width 2 to enclose SIMD pack
445 * width == 0 ? no enclose symbols
446 * width == 1 ? means enclose symbol begin and end are equal
447 * width >= 2 ? letter[0] = begin enclose symbol
448 * letter[1] = end enclose symbol
449 *
450 * example:
451 * .toString(";","|") -> |x;...;z|
452 * .toString(",","[]") -> [x,...,z]
453 */
454 std::string toString(std::string const separator = ",", std::string const enclosings = "{}") const
455 {
456 std::string locale_enclosing_begin;
457 std::string locale_enclosing_end;
458 size_t enclosingLaneIdx = enclosings.size();
459
460 if(enclosingLaneIdx > 0)
461 {
462 /* % avoid out of memory access */
463 locale_enclosing_begin = enclosings[0 % enclosingLaneIdx];
464 locale_enclosing_end = enclosings[1 % enclosingLaneIdx];
465 }
466
467 std::stringstream stream;
468 stream << locale_enclosing_begin << (*this)[0];
469
470 for(uint32_t i = 1u; i < T_width; ++i)
471 stream << separator << (*this)[i];
472 stream << locale_enclosing_end;
473 return stream.str();
474 }
475
476 private:
477 template<typename F, uint32_t... Is>
478 constexpr explicit Simd(F&& generator, std::integer_sequence<uint32_t, Is...>)
479 : Storage{generator(std::integral_constant<uint32_t, Is>{})...}
480 {
481 }
482
483 /** reduce over a range of elements
484 *
485 * @tparam BinaryOp binary functor executed to reduce the range
486 * @tparam T_start start index
487 * @tparam T_end end index (excluded)
488 * @return the type of the result depends on the binary functor
489 */
490 template<uint32_t T_start = 0u, uint32_t T_end = width()>
491 [[nodiscard]] constexpr auto reduce_range(auto&& reduceFunc) const
492 -> decltype(reduceFunc(std::declval<type>(), std::declval<type>()))
493 {
494 // elements in the range
495 constexpr uint32_t size = T_end - T_start;
496 // single element termination
497 if constexpr(size == 1u)
498 {
499 return (*this)[T_start];
500 }
501#if ALPAKA_LANG_SYCL
502 // SYCL can not call recursive functions
503 auto result = (*this)[T_start];
504 for(uint32_t i = T_start + 1u; i < T_end; ++i)
505 {
506 result = reduceFunc(result, (*this)[i]);
507 }
508 return result;
509#else
510 // split range at midpoint
511 constexpr uint32_t mid = T_start + size / 2u;
512
513 // recursively reduce both halves and combine
514 return reduceFunc(
515 reduce_range<T_start, mid>(ALPAKA_FORWARD(reduceFunc)),
516 reduce_range<mid, T_end>(ALPAKA_FORWARD(reduceFunc)));
517#endif
518 }
519
520 template<concepts::SimdMask Mask, concepts::Simd T_Simd>
521 friend struct SimdWhereExpr;
522 };
523
524 template<std::size_t I, typename T_Type, uint32_t T_width, typename T_Storage>
525 constexpr auto get(Simd<T_Type, T_width, T_Storage> const& v)
526 {
527 return v[I];
528 }
529
530 template<std::size_t I, typename T_Type, uint32_t T_width, typename T_Storage>
532 {
533 return v[I];
534 }
535
536 template<typename Type, uint32_t T_width, typename T_Storage>
537 std::ostream& operator<<(std::ostream& s, Simd<Type, T_width, T_Storage> const& vec)
538 {
539 return s << vec.toString();
540 }
541
542 // type deduction guide
543 template<typename T_1, typename... T_Args>
544 ALPAKA_FN_HOST_ACC Simd(T_1, T_Args...) -> Simd<T_1, uint32_t(sizeof...(T_Args) + 1u)>;
545
546 /** binary operators
547 * @{
548 */
549#define ALPAKA_VECTOR_BINARY_OP(typenameOrConcept, op) \
550 template<typenameOrConcept T_Type, uint32_t T_width, typename T_Storage, typename T_OtherStorage> \
551 constexpr auto operator op( \
552 const Simd<T_Type, T_width, T_Storage>& lhs, \
553 const Simd<T_Type, T_width, T_OtherStorage>& rhs) \
554 { \
555 using StoreageType = ALPAKA_TYPEOF(lhs.asStorage() op rhs.asStorage()); \
556 return Simd<T_Type, T_width, StoreageType>(lhs.asStorage() op rhs.asStorage()); \
557 } \
558 template< \
559 typenameOrConcept T_Type, \
560 concepts::LosslesslyConvertible<T_Type> T_ValueType, \
561 uint32_t T_width, \
562 typename T_Storage> \
563 constexpr auto operator op(const Simd<T_Type, T_width, T_Storage>& lhs, T_ValueType rhs) \
564 { \
565 using StoreageType = ALPAKA_TYPEOF(lhs.asStorage() op static_cast<T_Type>(rhs)); \
566 return Simd<T_Type, T_width, StoreageType>(lhs.asStorage() op static_cast<T_Type>(rhs)); \
567 } \
568 template< \
569 typenameOrConcept T_Type, \
570 concepts::LosslesslyConvertible<T_Type> T_ValueType, \
571 uint32_t T_width, \
572 typename T_Storage> \
573 constexpr auto operator op(T_ValueType lhs, const Simd<T_Type, T_width, T_Storage>& rhs) \
574 { \
575 using StoreageType = ALPAKA_TYPEOF(static_cast<T_Type>(lhs) op rhs.asStorage()); \
576 return Simd<T_Type, T_width, StoreageType>(static_cast<T_Type>(lhs) op rhs.asStorage()); \
577 }
578
589
590#undef ALPAKA_VECTOR_BINARY_OP
591
592
593#define ALPAKA_VECTOR_BINARY_CMP_OP(typenameOrConcept, op) \
594 template<typenameOrConcept T_Type, uint32_t T_width, typename T_Storage, typename T_OtherStorage> \
595 constexpr auto operator op( \
596 const Simd<T_Type, T_width, T_Storage>& lhs, \
597 const Simd<T_Type, T_width, T_OtherStorage>& rhs) \
598 { \
599 using StoreageType = ALPAKA_TYPEOF(lhs.asStorage() op rhs.asStorage()); \
600 return SimdMask<T_Type, T_width, StoreageType>(lhs.asStorage() op rhs.asStorage()); \
601 } \
602 template< \
603 typenameOrConcept T_Type, \
604 concepts::LosslesslyConvertible<T_Type> T_ValueType, \
605 uint32_t T_width, \
606 typename T_Storage> \
607 constexpr auto operator op(const Simd<T_Type, T_width, T_Storage>& lhs, T_ValueType rhs) \
608 { \
609 using StoreageType = ALPAKA_TYPEOF(lhs.asStorage() op static_cast<T_Type>(rhs)); \
610 return SimdMask<T_Type, T_width, StoreageType>(lhs.asStorage() op static_cast<T_Type>(rhs)); \
611 } \
612 template< \
613 typenameOrConcept T_Type, \
614 concepts::LosslesslyConvertible<T_Type> T_ValueType, \
615 uint32_t T_width, \
616 typename T_Storage> \
617 constexpr auto operator op(T_ValueType lhs, const Simd<T_Type, T_width, T_Storage>& rhs) \
618 { \
619 using StoreageType = ALPAKA_TYPEOF(static_cast<T_Type>(lhs) op rhs.asStorage()); \
620 return SimdMask<T_Type, T_width, StoreageType>(static_cast<T_Type>(lhs) op rhs.asStorage()); \
621 }
622
629
630#undef ALPAKA_VECTOR_BINARY_CMP_OP
631
632 /** @} */
633
634
635 namespace trait
636 {
637 template<typename T_Type, uint32_t T_width, typename T_Storage>
638 struct GetDim<alpaka::Simd<T_Type, T_width, T_Storage>>
639 {
640 static constexpr uint32_t value = T_width;
641 };
642
643 template<typename T_Type, uint32_t T_width, typename T_Storage>
644 struct GetValueType<alpaka::Simd<T_Type, T_width, T_Storage>>
645 {
646 using type = T_Type;
647 };
648 } // namespace trait
649
650 namespace internal
651 {
652 template<typename T_To, typename T_Type, uint32_t T_width, typename T_Storage>
653 struct PCast::Op<T_To, alpaka::Simd<T_Type, T_width, T_Storage>>
654 {
655 constexpr auto operator()(auto&& input) const
656 requires std::convertible_to<T_Type, T_To> && (!std::same_as<T_To, T_Type>)
657 {
659 [&](uint32_t idx) constexpr { return static_cast<T_To>(input[idx]); });
660 }
661
662 constexpr decltype(auto) operator()(auto&& input) const requires std::same_as<T_To, T_Type>
663 {
664 return std::forward<decltype(input)>(input);
665 }
666 };
667 } // namespace internal
668}; // namespace alpaka
669
670namespace std
671{
672 template<typename T_Type, uint32_t T_width, typename T_Storage>
673 struct tuple_size<alpaka::Simd<T_Type, T_width, T_Storage>>
674 {
675 static constexpr std::size_t value = T_width;
676 };
677
678 template<std::size_t I, typename T_Type, uint32_t T_width, typename T_Storage>
679 struct tuple_element<I, alpaka::Simd<T_Type, T_width, T_Storage>>
680 {
681 using type = T_Type;
682 };
683} // namespace std
#define ALPAKA_NAMED_ARRAY_ACCESS(functionName, laneIdx)
Definition Simd.hpp:275
#define ALPAKA_VECTOR_BINARY_CMP_OP(typenameOrConcept, op)
binary operators
Definition Simd.hpp:593
#define ALPAKA_VECTOR_ASSIGN_OP(op)
assign operator
Definition Simd.hpp:232
#define ALPAKA_VECTOR_BINARY_OP(typenameOrConcept, op)
binary operators
Definition Simd.hpp:549
#define ALPAKA_FN_HOST_ACC
All functions that can be used on an accelerator have to be attributed with ALPAKA_FN_ACC or ALPAKA_F...
Definition common.hpp:32
#define ALPAKA_FORWARD(instance)
Perfectly forward an instance as argument.
Definition common.hpp:148
Concept to check for an alignment object.
Definition Alignment.hpp:89
constexpr auto alpaka
Definition fn.hpp:66
main alpaka namespace.
Definition alpaka.hpp:76
std::ostream & operator<<(std::ostream &os, concepts::BoundaryDirection auto const &bd)
constexpr auto thisApi()
provides the API used during the execution of the current code path
Definition api.hpp:26
constexpr decltype(auto) get(concepts::SpecializationOf< Dict > auto &t) noexcept
Definition Dict.hpp:156
ALPAKA_FN_HOST_ACC Simd(T_1, T_Args...) -> Simd< T_1, uint32_t(sizeof...(T_Args)+1u)>
STL namespace.
Simd vector.
Definition Simd.hpp:78
constexpr reference s1()
Definition Simd.hpp:312
constexpr reference s2()
Definition Simd.hpp:313
Simd< T_Type, T_width > UniSimd
Definition Simd.hpp:89
constexpr reference x()
Definition Simd.hpp:301
uint32_t size_type
Definition Simd.hpp:85
std::string toString(std::string const separator=",", std::string const enclosings="{}") const
create string out of the SIMD pack
Definition Simd.hpp:454
constexpr reference s0()
Definition Simd.hpp:311
constexpr Simd< type, T_numElements > rshrink(std::integral auto const startIdx) const
Shrink the number of elements of a vector.
Definition Simd.hpp:371
constexpr auto reduce(auto &&reduceFunc) const -> decltype(reduceFunc(std::declval< type >(), std::declval< type >()))
Definition Simd.hpp:426
constexpr reference sF()
Definition Simd.hpp:326
ALPAKA_FN_HOST_ACC Simd(F &&generator)
Initialize via a generator expression.
Definition Simd.hpp:128
constexpr reference a()
Definition Simd.hpp:309
constexpr reference s5()
Definition Simd.hpp:316
static consteval uint32_t width()
Number of components/lanes in the SIMD pack.
Definition Simd.hpp:176
constexpr Simd< type, T_width - 1u > remove() const
Removes a component.
Definition Simd.hpp:388
constexpr Simd & operator=(Simd &&)=default
constexpr auto & asStorage()
static cast the instance to the storage type
Definition Simd.hpp:105
constexpr Simd(Simd const &other)=default
constexpr Simd toRT() const
Definition Simd.hpp:207
constexpr reference s9()
Definition Simd.hpp:320
constexpr reference g()
Definition Simd.hpp:307
static constexpr auto fill(concepts::Convertible< T_Type > auto value)
Creates a Simd where all lanes are set to the same value.
Definition Simd.hpp:197
constexpr reference s4()
Definition Simd.hpp:315
constexpr reference r()
Definition Simd.hpp:306
constexpr Simd< T_Type, T_width - 1u > eraseBack() const
Shrink the SIMD pack.
Definition Simd.hpp:353
uint32_t rank_type
Definition Simd.hpp:86
constexpr reference sB()
Definition Simd.hpp:322
constexpr reference w()
Definition Simd.hpp:304
constexpr reference s6()
Definition Simd.hpp:317
constexpr reference z()
Definition Simd.hpp:303
constexpr Simd< T_Type, T_numElements > rshrink() const
Shrink the number of elements of a vector.
Definition Simd.hpp:339
constexpr reference sE()
Definition Simd.hpp:325
constexpr reference sD()
Definition Simd.hpp:324
constexpr type product() const
Returns product of all components.
Definition Simd.hpp:404
constexpr reference s8()
Definition Simd.hpp:319
constexpr auto min(Simd< T_Type, T_width, T_OtherStorage > const &rhs) const
Definition Simd.hpp:433
constexpr type operator[](std::integral auto const idx) const
access a lane by index
Definition Simd.hpp:270
constexpr auto const & asStorage() const
static cast the instance to the storage type
Definition Simd.hpp:110
constexpr type sum() const
Returns sum of all components.
Definition Simd.hpp:413
constexpr reference sA()
Definition Simd.hpp:321
constexpr Simd(T_Storage const &other)
Definition Simd.hpp:154
constexpr reference operator[](std::integral auto const idx)
access a lane by index
Definition Simd.hpp:261
constexpr reference y()
Definition Simd.hpp:302
uint32_t index_type
Definition Simd.hpp:84
constexpr reference s7()
Definition Simd.hpp:318
constexpr void copyTo(auto *data, concepts::Alignment auto alignment) const
Definition Simd.hpp:186
T_Storage Storage
Definition Simd.hpp:79
constexpr Simd & operator=(Simd const &)=default
typename T_Storage::value_type type
Definition Simd.hpp:80
typename T_Storage::reference reference
type is an implementation detail, can be a proxy type.
Definition Simd.hpp:82
ALPAKA_FN_HOST_ACC Simd(T_Args const &... args)
Constructor for SIMD pack.
Definition Simd.hpp:148
constexpr Simd()=default
constexpr reference sC()
Definition Simd.hpp:323
constexpr Simd operator-() const
Definition Simd.hpp:224
constexpr reference b()
Definition Simd.hpp:308
constexpr Simd revert() const
Definition Simd.hpp:212
constexpr void copyFrom(T_Type const *data, concepts::Alignment auto alignment)
Definition Simd.hpp:181
constexpr reference s3()
Definition Simd.hpp:314
constexpr Simd(Simd< T_Type, T_width, T_OtherStorage > const &other)
constructor allows changing the storage policy
Definition Simd.hpp:161