DPC++ Runtime
Runtime libraries for oneAPI DPC++
marray.hpp
Go to the documentation of this file.
1 //==----------------- marray.hpp --- Implements marray classes -------------==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #pragma once
10 
11 #include <CL/sycl/aliases.hpp>
15 #include <CL/sycl/half_type.hpp>
16 
18 namespace sycl {
19 
24 template <typename Type, std::size_t NumElements> class marray {
25  using DataT = Type;
26 
27 public:
28  using value_type = Type;
29  using reference = Type &;
30  using const_reference = const Type &;
31  using iterator = Type *;
32  using const_iterator = const Type *;
33 
34 private:
35  value_type MData[NumElements];
36 
37  template <class...> struct conjunction : std::true_type {};
38  template <class B1, class... tail>
39  struct conjunction<B1, tail...>
40  : std::conditional<bool(B1::value), conjunction<tail...>, B1>::type {};
41 
42  // TypeChecker is needed for (const ArgTN &... Args) ctor to validate Args.
43  template <typename T, typename DataT_>
44  struct TypeChecker : std::is_convertible<T, DataT_> {};
45 
46  // Shortcuts for Args validation in (const ArgTN &... Args) ctor.
47  template <typename... ArgTN>
48  using EnableIfSuitableTypes = typename std::enable_if<
49  conjunction<TypeChecker<ArgTN, DataT>...>::value>::type;
50 
51  constexpr void initialize_data(const Type &Arg) {
52  for (size_t i = 0; i < NumElements; ++i) {
53  MData[i] = Arg;
54  }
55  }
56 
57 public:
58  constexpr marray() : MData{} {}
59 
60  explicit constexpr marray(const Type &Arg) : MData{Arg} {
61  initialize_data(Arg);
62  }
63 
64  template <
65  typename... ArgTN, typename = EnableIfSuitableTypes<ArgTN...>,
66  typename = typename std::enable_if<sizeof...(ArgTN) == NumElements>::type>
67  constexpr marray(const ArgTN &... Args) : MData{Args...} {}
68 
69  constexpr marray(const marray<Type, NumElements> &Rhs) = default;
70 
71  constexpr marray(marray<Type, NumElements> &&Rhs) = default;
72 
73  // Available only when: NumElements == 1
74  template <std::size_t Size = NumElements,
75  typename = typename std::enable_if<Size == 1>>
76  operator Type() const {
77  return MData[0];
78  }
79 
80  static constexpr std::size_t size() noexcept { return NumElements; }
81 
82  // subscript operator
83  reference operator[](std::size_t index) { return MData[index]; }
84 
85  const_reference operator[](std::size_t index) const { return MData[index]; }
86 
87  marray &operator=(const marray<Type, NumElements> &Rhs) = default;
88 
89  // broadcasting operator
90  marray &operator=(const Type &Rhs) {
91  for (std::size_t I = 0; I < NumElements; ++I) {
92  MData[I] = Rhs;
93  }
94  return *this;
95  }
96 
97  // iterator functions
98  iterator begin() { return MData; }
99 
100  const_iterator begin() const { return MData; }
101 
102  iterator end() { return MData + NumElements; }
103 
104  const_iterator end() const { return MData + NumElements; }
105 
106 #ifdef __SYCL_BINOP
107 #error "Undefine __SYCL_BINOP macro"
108 #endif
109 
110 #ifdef __SYCL_BINOP_INTEGRAL
111 #error "Undefine __SYCL_BINOP_INTEGRAL macro"
112 #endif
113 
114 #define __SYCL_BINOP(BINOP, OPASSIGN) \
115  friend marray operator BINOP(const marray &Lhs, const marray &Rhs) { \
116  marray Ret; \
117  for (size_t I = 0; I < NumElements; ++I) { \
118  Ret[I] = Lhs[I] BINOP Rhs[I]; \
119  } \
120  return Ret; \
121  } \
122  template <typename T> \
123  friend typename std::enable_if< \
124  std::is_convertible<DataT, T>::value && \
125  (std::is_fundamental<T>::value || \
126  std::is_same<typename std::remove_const<T>::type, half>::value), \
127  marray>::type \
128  operator BINOP(const marray &Lhs, const T &Rhs) { \
129  return Lhs BINOP marray(static_cast<DataT>(Rhs)); \
130  } \
131  friend marray &operator OPASSIGN(marray &Lhs, const marray &Rhs) { \
132  Lhs = Lhs BINOP Rhs; \
133  return Lhs; \
134  } \
135  template <std::size_t Num = NumElements> \
136  friend typename std::enable_if<Num != 1, marray &>::type operator OPASSIGN( \
137  marray &Lhs, const DataT &Rhs) { \
138  Lhs = Lhs BINOP marray(Rhs); \
139  return Lhs; \
140  }
141 
142 #define __SYCL_BINOP_INTEGRAL(BINOP, OPASSIGN) \
143  template <typename T = DataT, \
144  typename = std::enable_if<std::is_integral<T>::value, marray>> \
145  friend marray operator BINOP(const marray &Lhs, const marray &Rhs) { \
146  marray Ret; \
147  for (size_t I = 0; I < NumElements; ++I) { \
148  Ret[I] = Lhs[I] BINOP Rhs[I]; \
149  } \
150  return Ret; \
151  } \
152  template <typename T, typename BaseT = DataT> \
153  friend typename std::enable_if<std::is_convertible<T, DataT>::value && \
154  std::is_integral<T>::value && \
155  std::is_integral<BaseT>::value, \
156  marray>::type \
157  operator BINOP(const marray &Lhs, const T &Rhs) { \
158  return Lhs BINOP marray(static_cast<DataT>(Rhs)); \
159  } \
160  template <typename T = DataT, \
161  typename = std::enable_if<std::is_integral<T>::value, marray>> \
162  friend marray &operator OPASSIGN(marray &Lhs, const marray &Rhs) { \
163  Lhs = Lhs BINOP Rhs; \
164  return Lhs; \
165  } \
166  template <std::size_t Num = NumElements, typename T = DataT> \
167  friend typename std::enable_if<Num != 1 && std::is_integral<T>::value, \
168  marray &>::type \
169  operator OPASSIGN(marray &Lhs, const DataT &Rhs) { \
170  Lhs = Lhs BINOP marray(Rhs); \
171  return Lhs; \
172  }
173 
174  __SYCL_BINOP(+, +=)
175  __SYCL_BINOP(-, -=)
176  __SYCL_BINOP(*, *=)
177  __SYCL_BINOP(/, /=)
178 
179  __SYCL_BINOP_INTEGRAL(%, %=)
180  __SYCL_BINOP_INTEGRAL(|, |=)
181  __SYCL_BINOP_INTEGRAL(&, &=)
182  __SYCL_BINOP_INTEGRAL(^, ^=)
183  __SYCL_BINOP_INTEGRAL(>>, >>=)
184  __SYCL_BINOP_INTEGRAL(<<, <<=)
185 #undef __SYCL_BINOP
186 #undef __SYCL_BINOP_INTEGRAL
187 
188 #ifdef __SYCL_RELLOGOP
189 #error "Undefine __SYCL_RELLOGOP macro"
190 #endif
191 
192 #ifdef __SYCL_RELLOGOP_INTEGRAL
193 #error "Undefine __SYCL_RELLOGOP_INTEGRAL macro"
194 #endif
195 
196 #define __SYCL_RELLOGOP(RELLOGOP) \
197  friend marray<bool, NumElements> operator RELLOGOP(const marray &Lhs, \
198  const marray &Rhs) { \
199  marray<bool, NumElements> Ret; \
200  for (size_t I = 0; I < NumElements; ++I) { \
201  Ret[I] = Lhs[I] RELLOGOP Rhs[I]; \
202  } \
203  return Ret; \
204  } \
205  template <typename T> \
206  friend typename std::enable_if<std::is_convertible<T, DataT>::value && \
207  (std::is_fundamental<T>::value || \
208  std::is_same<T, half>::value), \
209  marray<bool, NumElements>>::type \
210  operator RELLOGOP(const marray &Lhs, const T &Rhs) { \
211  return Lhs RELLOGOP marray(static_cast<const DataT &>(Rhs)); \
212  }
213 
214 #define __SYCL_RELLOGOP_INTEGRAL(RELLOGOP) \
215  template <typename T = DataT> \
216  friend typename std::enable_if<std::is_integral<T>::value, \
217  marray<bool, NumElements>>::type \
218  operator RELLOGOP(const marray &Lhs, const marray &Rhs) { \
219  marray<bool, NumElements> Ret; \
220  for (size_t I = 0; I < NumElements; ++I) { \
221  Ret[I] = Lhs[I] RELLOGOP Rhs[I]; \
222  } \
223  return Ret; \
224  } \
225  template <typename T, typename BaseT = DataT> \
226  friend typename std::enable_if<std::is_convertible<T, DataT>::value && \
227  std::is_integral<T>::value && \
228  std::is_integral<BaseT>::value, \
229  marray<bool, NumElements>>::type \
230  operator RELLOGOP(const marray &Lhs, const T &Rhs) { \
231  return Lhs RELLOGOP marray(static_cast<const DataT &>(Rhs)); \
232  }
233 
234  __SYCL_RELLOGOP(==)
235  __SYCL_RELLOGOP(!=)
236  __SYCL_RELLOGOP(>)
237  __SYCL_RELLOGOP(<)
238  __SYCL_RELLOGOP(>=)
239  __SYCL_RELLOGOP(<=)
240 
243 
244 #undef __SYCL_RELLOGOP
245 #undef __SYCL_RELLOGOP_INTEGRAL
246 
247 #ifdef __SYCL_UOP
248 #error "Undefine __SYCL_UOP macro"
249 #endif
250 
251 #define __SYCL_UOP(UOP, OPASSIGN) \
252  friend marray &operator UOP(marray &Lhs) { \
253  Lhs OPASSIGN 1; \
254  return Lhs; \
255  } \
256  friend marray operator UOP(marray &Lhs, int) { \
257  marray Ret(Lhs); \
258  Lhs OPASSIGN 1; \
259  return Ret; \
260  }
261 
262  __SYCL_UOP(++, +=)
263  __SYCL_UOP(--, -=)
264 #undef __SYCL_UOP
265 
266  // Available only when: dataT != cl_float && dataT != cl_double
267  // && dataT != cl_half
268  template <typename T = DataT>
269  friend typename std::enable_if<std::is_integral<T>::value, marray>::type
270  operator~(const marray &Lhs) {
271  marray Ret;
272  for (size_t I = 0; I < NumElements; ++I) {
273  Ret[I] = ~Lhs[I];
274  }
275  return Ret;
276  }
277 
280  for (size_t I = 0; I < NumElements; ++I) {
281  Ret[I] = !Lhs[I];
282  }
283  return Ret;
284  }
285 
286  friend marray operator+(const marray &Lhs) {
287  marray Ret;
288  for (size_t I = 0; I < NumElements; ++I) {
289  Ret[I] = +Lhs[I];
290  }
291  return Ret;
292  }
293 
294  friend marray operator-(const marray &Lhs) {
295  marray Ret;
296  for (size_t I = 0; I < NumElements; ++I) {
297  Ret[I] = -Lhs[I];
298  }
299  return Ret;
300  }
301 };
302 
303 #define __SYCL_MAKE_MARRAY_ALIAS(ALIAS, TYPE, N) \
304  using ALIAS##N = cl::sycl::marray<TYPE, N>;
305 
306 #define __SYCL_MAKE_MARRAY_ALIASES_FOR_ARITHMETIC_TYPES(N) \
307  __SYCL_MAKE_MARRAY_ALIAS(mchar, char, N) \
308  __SYCL_MAKE_MARRAY_ALIAS(mshort, short, N) \
309  __SYCL_MAKE_MARRAY_ALIAS(mint, int, N) \
310  __SYCL_MAKE_MARRAY_ALIAS(mlong, long, N) \
311  __SYCL_MAKE_MARRAY_ALIAS(mfloat, float, N) \
312  __SYCL_MAKE_MARRAY_ALIAS(mdouble, double, N) \
313  __SYCL_MAKE_MARRAY_ALIAS(mhalf, half, N)
314 
315 #define __SYCL_MAKE_MARRAY_ALIASES_FOR_SIGNED_AND_UNSIGNED_TYPES(N) \
316  __SYCL_MAKE_MARRAY_ALIAS(mschar, signed char, N) \
317  __SYCL_MAKE_MARRAY_ALIAS(muchar, unsigned char, N) \
318  __SYCL_MAKE_MARRAY_ALIAS(mushort, unsigned short, N) \
319  __SYCL_MAKE_MARRAY_ALIAS(muint, unsigned int, N) \
320  __SYCL_MAKE_MARRAY_ALIAS(mulong, unsigned long, N) \
321  __SYCL_MAKE_MARRAY_ALIAS(mlonglong, long long, N) \
322  __SYCL_MAKE_MARRAY_ALIAS(mulonglong, unsigned long long, N)
323 
324 #define __SYCL_MAKE_MARRAY_ALIASES_FOR_MARRAY_LENGTH(N) \
325  __SYCL_MAKE_MARRAY_ALIASES_FOR_ARITHMETIC_TYPES(N) \
326  __SYCL_MAKE_MARRAY_ALIASES_FOR_SIGNED_AND_UNSIGNED_TYPES(N)
327 
333 
334 #undef __SYCL_MAKE_MARRAY_ALIAS
335 #undef __SYCL_MAKE_MARRAY_ALIASES_FOR_ARITHMETIC_TYPES
336 #undef __SYCL_MAKE_MARRAY_ALIASES_FOR_SIGNED_AND_UNSIGNED_TYPES
337 #undef __SYCL_MAKE_MARRAY_ALIASES_FOR_MARRAY_LENGTH
338 
339 } // namespace sycl
340 } // __SYCL_INLINE_NAMESPACE(cl)
cl::sycl::marray::begin
iterator begin()
Definition: marray.hpp:98
cl::sycl::marray< T, Extent >::reference
T & reference
Definition: marray.hpp:29
__SYCL_BINOP
#define __SYCL_BINOP(BINOP, OPASSIGN)
Definition: marray.hpp:114
cl::sycl::marray< T, Extent >::value_type
T value_type
Definition: marray.hpp:28
type_traits.hpp
cl::sycl::marray::operator!
friend marray< bool, NumElements > operator!(const marray &Lhs)
Definition: marray.hpp:278
cl::sycl::marray::operator-
friend marray operator-(const marray &Lhs)
Definition: marray.hpp:294
sycl
Definition: invoke_simd.hpp:68
cl::sycl::marray::marray
constexpr marray(const ArgTN &... Args)
Definition: marray.hpp:67
cl::sycl::marray::operator[]
reference operator[](std::size_t index)
Definition: marray.hpp:83
cl::sycl::marray::operator[]
const_reference operator[](std::size_t index) const
Definition: marray.hpp:85
cl::sycl::marray::operator=
marray & operator=(const Type &Rhs)
Definition: marray.hpp:90
__SYCL_BINOP_INTEGRAL
#define __SYCL_BINOP_INTEGRAL(BINOP, OPASSIGN)
Definition: marray.hpp:142
cl::sycl::marray< T, Extent >::const_iterator
const T * const_iterator
Definition: marray.hpp:32
generic_type_traits.hpp
__SYCL_UOP
#define __SYCL_UOP(UOP, OPASSIGN)
Definition: marray.hpp:251
cl
We provide new interfaces for matrix muliply in this patch:
Definition: access.hpp:13
cl::sycl::marray::operator~
friend std::enable_if< std::is_integral< T >::value, marray >::type operator~(const marray &Lhs)
Definition: marray.hpp:270
cl::sycl::marray::marray
constexpr marray()
Definition: marray.hpp:58
cl::sycl::marray< T, Extent >::const_reference
const T & const_reference
Definition: marray.hpp:30
cl::sycl::marray::marray
constexpr marray(const Type &Arg)
Definition: marray.hpp:60
__SYCL_RELLOGOP_INTEGRAL
#define __SYCL_RELLOGOP_INTEGRAL(RELLOGOP)
Definition: marray.hpp:214
cl::sycl::marray::end
const_iterator end() const
Definition: marray.hpp:104
cl::sycl::marray
Provides a cross-patform math array class template that works on SYCL devices as well as in host C++ ...
Definition: generic_type_lists.hpp:24
half_type.hpp
aliases.hpp
__SYCL_RELLOGOP
#define __SYCL_RELLOGOP(RELLOGOP)
Definition: marray.hpp:196
common.hpp
cl::sycl::marray::begin
const_iterator begin() const
Definition: marray.hpp:100
cl::sycl::marray::size
static constexpr std::size_t size() noexcept
Definition: marray.hpp:80
cl::sycl::marray::operator+
friend marray operator+(const marray &Lhs)
Definition: marray.hpp:286
cl::sycl::marray< T, Extent >::iterator
T * iterator
Definition: marray.hpp:31
__SYCL_MAKE_MARRAY_ALIASES_FOR_MARRAY_LENGTH
#define __SYCL_MAKE_MARRAY_ALIASES_FOR_MARRAY_LENGTH(N)
Definition: marray.hpp:324
cl::sycl::marray::end
iterator end()
Definition: marray.hpp:102
__SYCL_INLINE_NAMESPACE
#define __SYCL_INLINE_NAMESPACE(X)
Definition: defines_elementary.hpp:12