19 #include <type_traits>
23 inline namespace _V1 {
25 template <
typename DataT, std::
size_t N>
class marray;
33 static constexpr std::size_t value = 0;
35 template <
typename T, std::size_t N,
typename... Ts>
49 template <
typename Type, std::
size_t NumElements>
class marray {
65 struct IsSuitableArgType : std::is_convertible<T, DataT> {};
66 template <
typename T,
size_t N>
67 struct IsSuitableArgType<
marray<T, N>> : std::is_convertible<T, DataT> {};
71 template <
typename... ArgTN>
72 struct AllSuitableArgTypes : std::conjunction<IsSuitableArgType<ArgTN>...> {};
75 template <
typename DataT,
typename T, std::size_t... Is>
76 static constexpr std::array<DataT,
sizeof...(Is)>
77 MArrayToArray(
const marray<T,
sizeof...(Is)> &A, std::index_sequence<Is...>) {
78 return {
static_cast<DataT
>(A.MData[Is])...};
80 template <
typename DataT,
typename T, std::
size_t N>
81 static constexpr std::array<DataT, N>
82 FlattenMArrayArgHelper(
const marray<T, N> &A) {
83 return MArrayToArray<DataT>(A, std::make_index_sequence<N>());
85 template <
typename DataT,
typename T>
86 static constexpr
auto FlattenMArrayArgHelper(
const T &A) {
87 return std::array<DataT, 1>{
static_cast<DataT
>(
A)};
89 template <
typename DataT,
typename T>
struct FlattenMArrayArg {
90 constexpr
auto operator()(
const T &A)
const {
91 return FlattenMArrayArgHelper<DataT>(A);
96 template <
typename DataT,
typename... ArgTN>
97 using MArrayArgArrayCreator =
98 detail::ArrayCreator<DataT, FlattenMArrayArg, ArgTN...>;
102 template <
typename Type_, std::
size_t NumElements_>
friend class marray;
104 constexpr
void initialize_data(
const Type &Arg) {
105 for (
size_t i = 0; i < NumElements; ++i) {
110 template <
size_t... Is>
111 constexpr
marray(
const std::array<DataT, NumElements> &Arr,
112 std::index_sequence<Is...>)
113 : MData{Arr[Is]...} {}
118 explicit constexpr
marray(
const Type &Arg) : MData{Arg} {
119 initialize_data(Arg);
122 template <
typename... ArgTN,
123 typename = std::enable_if_t<
124 AllSuitableArgTypes<ArgTN...>::value &&
128 std::make_index_sequence<NumElements>()} {}
135 template <std::size_t Size = NumElements,
136 typename = std::enable_if_t<Size == 1>>
137 operator Type()
const {
152 for (std::size_t I = 0; I < NumElements; ++I) {
168 #error "Undefine __SYCL_BINOP macro"
171 #ifdef __SYCL_BINOP_INTEGRAL
172 #error "Undefine __SYCL_BINOP_INTEGRAL macro"
175 #define __SYCL_BINOP(BINOP, OPASSIGN) \
176 friend marray operator BINOP(const marray &Lhs, const marray &Rhs) { \
178 for (size_t I = 0; I < NumElements; ++I) { \
179 Ret[I] = Lhs[I] BINOP Rhs[I]; \
183 template <typename T> \
184 friend typename std::enable_if_t< \
185 std::is_convertible_v<DataT, T> && \
186 (std::is_fundamental_v<T> || \
187 std::is_same_v<typename std::remove_const<T>::type, half>), \
189 operator BINOP(const marray &Lhs, const T &Rhs) { \
190 return Lhs BINOP marray(static_cast<DataT>(Rhs)); \
192 template <typename T> \
193 friend typename std::enable_if_t< \
194 std::is_convertible_v<DataT, T> && \
195 (std::is_fundamental_v<T> || \
196 std::is_same_v<typename std::remove_const<T>::type, half>), \
198 operator BINOP(const T &Lhs, const marray &Rhs) { \
199 return marray(static_cast<DataT>(Lhs)) BINOP Rhs; \
201 friend marray &operator OPASSIGN(marray &Lhs, const marray &Rhs) { \
202 Lhs = Lhs BINOP Rhs; \
205 template <std::size_t Num = NumElements> \
206 friend typename std::enable_if_t<Num != 1, marray &> operator OPASSIGN( \
207 marray &Lhs, const DataT &Rhs) { \
208 Lhs = Lhs BINOP marray(Rhs); \
212 #define __SYCL_BINOP_INTEGRAL(BINOP, OPASSIGN) \
213 template <typename T = DataT, \
214 typename = std::enable_if_t<std::is_integral_v<T>, marray>> \
215 friend marray operator BINOP(const marray &Lhs, const marray &Rhs) { \
217 for (size_t I = 0; I < NumElements; ++I) { \
218 Ret[I] = Lhs[I] BINOP Rhs[I]; \
222 template <typename T, typename BaseT = DataT> \
223 friend typename std::enable_if_t<std::is_convertible_v<T, DataT> && \
224 std::is_integral_v<T> && \
225 std::is_integral_v<BaseT>, \
227 operator BINOP(const marray &Lhs, const T &Rhs) { \
228 return Lhs BINOP marray(static_cast<DataT>(Rhs)); \
230 template <typename T, typename BaseT = DataT> \
231 friend typename std::enable_if_t<std::is_convertible_v<T, DataT> && \
232 std::is_integral_v<T> && \
233 std::is_integral_v<BaseT>, \
235 operator BINOP(const T &Lhs, const marray &Rhs) { \
236 return marray(static_cast<DataT>(Lhs)) BINOP Rhs; \
238 template <typename T = DataT, \
239 typename = std::enable_if_t<std::is_integral_v<T>, marray>> \
240 friend marray &operator OPASSIGN(marray &Lhs, const marray &Rhs) { \
241 Lhs = Lhs BINOP Rhs; \
244 template <std::size_t Num = NumElements, typename T = DataT> \
246 typename std::enable_if_t<Num != 1 && std::is_integral_v<T>, marray &> \
247 operator OPASSIGN(marray &Lhs, const DataT &Rhs) { \
248 Lhs = Lhs BINOP marray(Rhs); \
264 #undef __SYCL_BINOP_INTEGRAL
266 #ifdef __SYCL_RELLOGOP
267 #error "Undefine __SYCL_RELLOGOP macro"
270 #ifdef __SYCL_RELLOGOP_INTEGRAL
271 #error "Undefine __SYCL_RELLOGOP_INTEGRAL macro"
274 #define __SYCL_RELLOGOP(RELLOGOP) \
275 friend marray<bool, NumElements> operator RELLOGOP(const marray &Lhs, \
276 const marray &Rhs) { \
277 marray<bool, NumElements> Ret; \
278 for (size_t I = 0; I < NumElements; ++I) { \
279 Ret[I] = Lhs[I] RELLOGOP Rhs[I]; \
283 template <typename T> \
284 friend typename std::enable_if_t<std::is_convertible_v<T, DataT> && \
285 (std::is_fundamental_v<T> || \
286 std::is_same_v<T, half>), \
287 marray<bool, NumElements>> \
288 operator RELLOGOP(const marray &Lhs, const T &Rhs) { \
289 return Lhs RELLOGOP marray(static_cast<const DataT &>(Rhs)); \
291 template <typename T> \
292 friend typename std::enable_if_t<std::is_convertible_v<T, DataT> && \
293 (std::is_fundamental_v<T> || \
294 std::is_same_v<T, half>), \
295 marray<bool, NumElements>> \
296 operator RELLOGOP(const T &Lhs, const marray &Rhs) { \
297 return marray(static_cast<const DataT &>(Lhs)) RELLOGOP Rhs; \
309 #undef __SYCL_RELLOGOP
312 #error "Undefine __SYCL_UOP macro"
315 #define __SYCL_UOP(UOP, OPASSIGN) \
316 template <typename T = DataT> \
317 friend std::enable_if_t< \
318 !std::is_same_v<typename std::remove_cv<T>::type, bool>, marray> \
319 &operator UOP(marray & Lhs) { \
323 template <typename T = DataT> \
324 friend std::enable_if_t< \
325 !std::is_same_v<typename std::remove_cv<T>::type, bool>, marray> \
326 operator UOP(marray & Lhs, int) { \
331 template <typename T = DataT> \
333 "++ and -- operators are deprecated for marray<bool, ...>") \
334 friend std::enable_if_t< \
335 std::is_same_v<typename std::remove_cv<T>::type, bool>, marray> \
336 &operator UOP(marray & Lhs) { \
340 template <typename T = DataT> \
342 "++ and -- operators are deprecated for marray<bool, ...>") \
343 friend std::enable_if_t< \
344 std::is_same_v<typename std::remove_cv<T>::type, bool>, marray> \
345 operator UOP(marray & Lhs, int) { \
357 template <
typename T = DataT>
358 friend std::enable_if_t<std::is_integral_v<T>,
marray>
361 for (
size_t I = 0; I < NumElements; ++I) {
369 for (
size_t I = 0; I < NumElements; ++I) {
377 for (
size_t I = 0; I < NumElements; ++I) {
385 for (
size_t I = 0; I < NumElements; ++I) {
393 template <
typename T, std::
size_t N>
396 #define __SYCL_MAKE_MARRAY_ALIAS(ALIAS, TYPE, N) \
397 using ALIAS##N = sycl::marray<TYPE, N>;
399 #define __SYCL_MAKE_MARRAY_ALIASES_FOR_ARITHMETIC_TYPES(N) \
400 __SYCL_MAKE_MARRAY_ALIAS(mbool, bool, N) \
401 __SYCL_MAKE_MARRAY_ALIAS(mchar, std::int8_t, N) \
402 __SYCL_MAKE_MARRAY_ALIAS(mshort, std::int16_t, N) \
403 __SYCL_MAKE_MARRAY_ALIAS(mint, std::int32_t, N) \
404 __SYCL_MAKE_MARRAY_ALIAS(mlong, std::int64_t, N) \
405 __SYCL_MAKE_MARRAY_ALIAS(mlonglong, std::int64_t, N) \
406 __SYCL_MAKE_MARRAY_ALIAS(mfloat, float, N) \
407 __SYCL_MAKE_MARRAY_ALIAS(mdouble, double, N) \
408 __SYCL_MAKE_MARRAY_ALIAS(mhalf, half, N)
414 #define __SYCL_MAKE_MARRAY_ALIASES_FOR_SIGNED_AND_UNSIGNED_TYPES(N) \
415 __SYCL_MAKE_MARRAY_ALIAS(mschar, std::int8_t, N) \
416 __SYCL_MAKE_MARRAY_ALIAS(muchar, std::uint8_t, N) \
417 __SYCL_MAKE_MARRAY_ALIAS(mushort, std::uint16_t, N) \
418 __SYCL_MAKE_MARRAY_ALIAS(muint, std::uint32_t, N) \
419 __SYCL_MAKE_MARRAY_ALIAS(mulong, std::uint64_t, N) \
420 __SYCL_MAKE_MARRAY_ALIAS(mulonglong, std::uint64_t, N)
422 #define __SYCL_MAKE_MARRAY_ALIASES_FOR_MARRAY_LENGTH(N) \
423 __SYCL_MAKE_MARRAY_ALIASES_FOR_ARITHMETIC_TYPES(N) \
424 __SYCL_MAKE_MARRAY_ALIASES_FOR_SIGNED_AND_UNSIGNED_TYPES(N)
432 #undef __SYCL_MAKE_MARRAY_ALIAS
433 #undef __SYCL_MAKE_MARRAY_ALIASES_FOR_ARITHMETIC_TYPES
434 #undef __SYCL_MAKE_MARRAY_ALIASES_FOR_SIGNED_AND_UNSIGNED_TYPES
435 #undef __SYCL_MAKE_MARRAY_ALIASES_FOR_MARRAY_LENGTH
Provides a cross-platform math array class template that works on SYCL devices as well as in host C++...
const_reference operator[](std::size_t index) const
constexpr marray(const ArgTN &...Args)
const Type * const_iterator
static constexpr std::size_t size() noexcept
const Type & const_reference
friend marray< bool, NumElements > operator!(const marray &Lhs)
friend std::enable_if_t< std::is_integral_v< T >, marray > operator~(const marray &Lhs)
friend marray operator-(const marray &Lhs)
const_iterator begin() const
friend marray operator+(const marray &Lhs)
constexpr marray(const marray< Type, NumElements > &Rhs)=default
constexpr marray(const Type &Arg)
reference operator[](std::size_t index)
const_iterator end() const
marray & operator=(const marray< Type, NumElements > &Rhs)=default
constexpr marray(marray< Type, NumElements > &&Rhs)=default
marray & operator=(const Type &Rhs)
#define __SYCL_UOP(UOP, OPASSIGN)
#define __SYCL_BINOP_INTEGRAL(BINOP, OPASSIGN)
#define __SYCL_MAKE_MARRAY_ALIASES_FOR_MARRAY_LENGTH(N)
#define __SYCL_RELLOGOP(RELLOGOP)
#define __SYCL_BINOP(BINOP, OPASSIGN)
_Abi const simd< _Tp, _Abi > & noexcept
is_device_copyable is a user specializable class template to indicate that a type T is device copyabl...