alpaka
Abstraction Library for Parallel Kernel Acceleration
Loading...
Searching...
No Matches
EmuSimdMask.hpp
Go to the documentation of this file.
1/* Copyright 2026 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/api/api.hpp"
22#include "alpaka/simd/trait.hpp"
23
24#include <concepts>
25#include <type_traits>
26
27namespace alpaka
28{
29 namespace internal
30 {
31 template<typename T_Type, uint32_t T_width>
32 struct alignas(alpaka::internal::optimalAlignment<
34 ALPAKA_TYPEOF(internal::valueMaskCast<T_Type>(true)),
36 T_width,
38 Alignment<sizeof(ALPAKA_TYPEOF(internal::valueMaskCast<T_Type>(true))) * T_width>>())
39 EmuSimdMask : protected std::array<ALPAKA_TYPEOF(internal::valueMaskCast<T_Type>(true)), T_width>
40 {
41 using ValueMaskType = ALPAKA_TYPEOF(internal::valueMaskCast<T_Type>(true));
42
43 using BaseType = std::array<ValueMaskType, T_width>;
44
45 using value_type = bool;
46 using reference = SmartMaskValueRef<bool, ValueMaskType>;
47
48 using BaseType::operator[];
49
50 constexpr reference operator[](std::integral auto const idx)
51 {
52 return reference(BaseType::operator[](idx));
53 }
54
55 constexpr EmuSimdMask() = default;
56
57 constexpr EmuSimdMask(EmuSimdMask const& other)
58 {
59 // attention: using default constructor results in bad performance
60 for(uint32_t i = 0u; i < T_width; ++i)
61 BaseType::operator[](i) = other[i];
62 }
63
64 constexpr EmuSimdMask(EmuSimdMask&&) = default;
65
66 constexpr EmuSimdMask& operator=(EmuSimdMask&& rhs) = default;
67
68 constexpr EmuSimdMask& operator=(EmuSimdMask const& rhs) = default;
69
70 constexpr EmuSimdMask& operator=(T_Type const value)
71 {
72 for(uint32_t i = 0u; i < T_width; i++)
73 {
74 asNativeType()[i] = value;
75 }
76 return *this;
77 }
78
79 // constructor is required because exposing the array constructors does not work
80 template<typename... T_Args>
81 requires(sizeof...(T_Args) == T_width && (std::same_as<T_Args, T_Type> && ...))
82 constexpr EmuSimdMask(T_Args const&... args) : BaseType{args...}
83 {
84 }
85
86 template<typename... T_Args>
87 requires(sizeof...(T_Args) == T_width && (std::same_as<T_Args, bool> && ...))
88 constexpr EmuSimdMask(T_Args... args) : BaseType{valueMaskCast<T_Type>(args)...}
89 {
90 }
91
92 constexpr EmuSimdMask(BaseType const& base) : BaseType{base}
93 {
94 }
95
96 /** static cast the instance to the parent class
97 *
98 * This method is mostly used to get access to native comparison operators.
99 * @{
100 */
101 constexpr auto& asNativeType()
102 {
103 return static_cast<EmuSimdMask&>(*this);
104 }
105
106 constexpr auto const& asNativeType() const
107 {
108 return static_cast<EmuSimdMask const&>(*this);
109 }
110
111 /** @} */
112
113 static constexpr auto fill(bool value)
114 {
115 auto maskValue = valueMaskCast<T_Type>(value);
116 BaseType ret{};
117 for(uint32_t i = 0u; i < T_width; ++i)
118 ret[i] = maskValue;
119
120 return EmuSimdMask(ret);
121 }
122
123 constexpr void copyFrom(T_Type const* data, alpaka::concepts::Alignment auto alignment)
124 {
125 if constexpr((alignment.template get<T_Type>() % alignof(ALPAKA_TYPEOF(*this))) == 0u)
126 *(this) = *reinterpret_cast<ALPAKA_TYPEOF(*this) const*>(data);
127 else
128 {
129 for(uint32_t i = 0u; i < T_width; ++i)
130 asNativeType()[i] = data[i];
131 }
132 }
133
134 constexpr void copyTo(auto* data, alpaka::concepts::Alignment auto alignment) const
135 {
136 if constexpr((alignment.template get<T_Type>() % alignof(ALPAKA_TYPEOF(*this))) == 0u)
137 *reinterpret_cast<ALPAKA_TYPEOF(*this) const*>(data) = (*this);
138 else
139 {
140 for(uint32_t i = 0u; i < T_width; ++i)
141 data[i] = asNativeType()[i];
142 }
143 }
145 /** assign operator
146 */
147#define ALPAKA_VECTOR_ASSIGN_OP(op) \
148 template<typename T_OtherStorage> \
149 constexpr EmuSimdMask& operator op(EmuSimdMask const& rhs) \
150 { \
151 for(uint32_t i = 0u; i < T_width; i++) \
152 { \
153 asNativeType()[i] op rhs[i]; \
154 } \
155 return *this; \
156 } \
157 constexpr EmuSimdMask& operator op(T_Type const value) \
158 { \
159 for(uint32_t i = 0u; i < T_width; i++) \
160 { \
161 asNativeType()[i] op value; \
162 } \
163 return *this; \
164 }
168
169#undef ALPAKA_VECTOR_ASSIGN_OP
170 };
171
172#define ALPAKA_VECTOR_BINARY_CMP_OP(returnSimdType, argSimdType, typenameOrConcept, op) \
173 template<typenameOrConcept T_Type, uint32_t T_width> \
174 constexpr auto operator op(const argSimdType<T_Type, T_width>& lhs, const argSimdType<T_Type, T_width>& rhs) \
175 { \
176 returnSimdType<T_Type, T_width> ret{}; \
177 for(uint32_t i = 0u; i < T_width; i++) \
178 ret[i] = valueMaskCast<T_Type>(lhs[i] op rhs[i]); \
179 return ret; \
180 } \
181 template<typenameOrConcept T_Type, uint32_t T_width> \
182 constexpr auto operator op(const argSimdType<T_Type, T_width>& lhs, T_Type rhs) \
183 { \
184 returnSimdType<T_Type, T_width> ret{}; \
185 for(uint32_t i = 0u; i < T_width; i++) \
186 ret[i] = valueMaskCast<T_Type>(lhs[i] op rhs); \
187 return ret; \
188 } \
189 template<typenameOrConcept T_Type, uint32_t T_width> \
190 constexpr auto operator op(T_Type lhs, const argSimdType<T_Type, T_width>& rhs) \
191 { \
192 returnSimdType<T_Type, T_width> ret{}; \
193 for(uint32_t i = 0u; i < T_width; i++) \
194 ret[i] = valueMaskCast<T_Type>(lhs op rhs[i]); \
195 return ret; \
196 }
197
198 ALPAKA_VECTOR_BINARY_CMP_OP(EmuSimdMask, EmuSimd, typename, >=)
199 ALPAKA_VECTOR_BINARY_CMP_OP(EmuSimdMask, EmuSimd, typename, >)
200 ALPAKA_VECTOR_BINARY_CMP_OP(EmuSimdMask, EmuSimd, typename, <=)
201 ALPAKA_VECTOR_BINARY_CMP_OP(EmuSimdMask, EmuSimd, typename, <)
202 ALPAKA_VECTOR_BINARY_CMP_OP(EmuSimdMask, EmuSimd, typename, ==)
203 ALPAKA_VECTOR_BINARY_CMP_OP(EmuSimdMask, EmuSimd, typename, !=)
204
205 ALPAKA_VECTOR_BINARY_CMP_OP(EmuSimdMask, EmuSimdMask, typename, ==)
206 ALPAKA_VECTOR_BINARY_CMP_OP(EmuSimdMask, EmuSimdMask, typename, !=)
207 ALPAKA_VECTOR_BINARY_CMP_OP(EmuSimdMask, EmuSimdMask, typename, &&)
208 ALPAKA_VECTOR_BINARY_CMP_OP(EmuSimdMask, EmuSimdMask, typename, ||)
209
210#undef ALPAKA_VECTOR_BINARY_CMP_OP
211 } // namespace internal
212
213 namespace trait
214 {
215 template<concepts::Api T_Api, typename T_Type, uint32_t T_width>
217 {
218 using type = internal::EmuSimdMask<T_Type, T_width>;
}; } // namespace trait} // namespace alpaka
#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_TYPEOF(...)
Get the type of instance.
Definition common.hpp:153
decltype(auto) data(auto &&any)
pointer to data of an object
main alpaka namespace.
Definition alpaka.hpp:76
constexpr decltype(auto) get(concepts::SpecializationOf< Dict > auto &t) noexcept
Definition Dict.hpp:151
Get the storage type for a SIMD mask pack.
internal::EmuSimdMask< T_Type, T_width > type