@@ -62,6 +62,52 @@ struct UnaryPlus {
62
62
// Tag to map/templatize the mixin for prefix/postfix inc/dec operators.
63
63
struct IncDec {};
64
64
65
+ template <class T > static constexpr bool not_fp = !is_vgenfloat_v<T>;
66
+
67
+ // To provide information about operators availability depending on vec/swizzle
68
+ // element type.
69
+ template <typename Op, typename T>
70
+ inline constexpr bool is_op_available_for_type = false ;
71
+
72
+ #define __SYCL_OP_AVAILABILITY (OP, COND ) \
73
+ template <typename T> \
74
+ inline constexpr bool is_op_available_for_type<OP, T> = COND;
75
+
76
+ // clang-format off
77
+ __SYCL_OP_AVAILABILITY (std::plus<void > , true )
78
+ __SYCL_OP_AVAILABILITY (std::minus<void > , true )
79
+ __SYCL_OP_AVAILABILITY (std::multiplies<void > , true )
80
+ __SYCL_OP_AVAILABILITY (std::divides<void > , true )
81
+ __SYCL_OP_AVAILABILITY (std::modulus<void > , not_fp<T>)
82
+
83
+ __SYCL_OP_AVAILABILITY (std::bit_and<void > , not_fp<T>)
84
+ __SYCL_OP_AVAILABILITY (std::bit_or<void > , not_fp<T>)
85
+ __SYCL_OP_AVAILABILITY (std::bit_xor<void > , not_fp<T>)
86
+
87
+ __SYCL_OP_AVAILABILITY (std::equal_to<void > , true )
88
+ __SYCL_OP_AVAILABILITY (std::not_equal_to<void > , true )
89
+ __SYCL_OP_AVAILABILITY (std::less<void > , true )
90
+ __SYCL_OP_AVAILABILITY (std::greater<void > , true )
91
+ __SYCL_OP_AVAILABILITY (std::less_equal<void > , true )
92
+ __SYCL_OP_AVAILABILITY (std::greater_equal<void > , true )
93
+
94
+ __SYCL_OP_AVAILABILITY (std::logical_and<void > , not_fp<T>)
95
+ __SYCL_OP_AVAILABILITY (std::logical_or<void > , not_fp<T>)
96
+
97
+ __SYCL_OP_AVAILABILITY (ShiftLeft , not_fp<T>)
98
+ __SYCL_OP_AVAILABILITY (ShiftRight , not_fp<T>)
99
+
100
+ // Unary
101
+ __SYCL_OP_AVAILABILITY (std::negate<void > , true )
102
+ __SYCL_OP_AVAILABILITY (std::logical_not<void > , true )
103
+ __SYCL_OP_AVAILABILITY (std::bit_not<void > , not_fp<T>)
104
+ __SYCL_OP_AVAILABILITY (UnaryPlus , true )
105
+
106
+ __SYCL_OP_AVAILABILITY (IncDec , true )
107
+ // clang-format on
108
+
109
+ #undef __SYCL_OP_AVAILABILITY
110
+
65
111
template <typename SelfOperandTy> struct IncDecImpl {
66
112
using element_type = typename from_incomplete<SelfOperandTy>::element_type;
67
113
using vec_t = simplify_if_swizzle_t <std::remove_const_t <SelfOperandTy>>;
@@ -213,7 +259,8 @@ template <typename Self> struct VecOperators {
213
259
template <typename Op>
214
260
struct OpMixin <Op, std::enable_if_t <std::is_same_v<Op, std::bit_not<void >>>> {
215
261
template <typename T = typename from_incomplete<Self>::element_type>
216
- friend std::enable_if_t <!is_vgenfloat_v<T>, Self> operator ~(const Self &v) {
262
+ friend std::enable_if_t <is_op_available_for_type<Op, T>, Self>
263
+ operator ~(const Self &v) {
217
264
return apply<std::bit_not<void >>(v);
218
265
}
219
266
};
@@ -233,32 +280,33 @@ template <typename Self> struct VecOperators {
233
280
#error "Undefine __SYCL_BINOP macro"
234
281
#endif
235
282
236
- #define __SYCL_BINOP (BINOP, OPASSIGN, COND, FUNCTOR ) \
283
+ #define __SYCL_BINOP (BINOP, OPASSIGN, FUNCTOR ) \
237
284
template <typename T = DataT> \
238
- friend std::enable_if_t <(COND), vec_t > operator BINOP ( const vec_t & Lhs, \
239
- const vec_t & Rhs) { \
285
+ friend std::enable_if_t <is_op_available_for_type<FUNCTOR, T>, vec_t > \
286
+ operator BINOP ( const vec_t & Lhs, const vec_t & Rhs) { \
240
287
return VecOperators<vec_t >::template apply<FUNCTOR>(Lhs, Rhs); \
241
288
} \
242
289
\
243
290
template <typename T = DataT> \
244
- friend std::enable_if_t <(COND), vec_t > operator BINOP ( const vec_t & Lhs, \
245
- const DataT & Rhs) { \
291
+ friend std::enable_if_t <is_op_available_for_type<FUNCTOR, T>, vec_t > \
292
+ operator BINOP ( const vec_t & Lhs, const DataT & Rhs) { \
246
293
return Lhs BINOP vec_t (Rhs); \
247
294
} \
248
295
template <typename T = DataT> \
249
- friend std::enable_if_t <(COND), vec_t > operator BINOP ( const DataT & Lhs, \
250
- const vec_t & Rhs) { \
296
+ friend std::enable_if_t <is_op_available_for_type<FUNCTOR, T>, vec_t > \
297
+ operator BINOP ( const DataT & Lhs, const vec_t & Rhs) { \
251
298
return vec_t (Lhs) BINOP Rhs; \
252
299
} \
253
300
template <typename T = DataT> \
254
- friend std::enable_if_t <(COND), vec_t > & operator OPASSIGN ( \
255
- vec_t & Lhs, const vec_t & Rhs) { \
301
+ friend std::enable_if_t <is_op_available_for_type<FUNCTOR, T>, vec_t > \
302
+ & operator OPASSIGN ( vec_t & Lhs, const vec_t & Rhs) { \
256
303
Lhs = Lhs BINOP Rhs; \
257
304
return Lhs; \
258
305
} \
259
306
template <int Num = NumElements, typename T = DataT> \
260
- friend std::enable_if_t <(Num != 1 ) && (COND), vec_t &> operator OPASSIGN ( \
261
- vec_t & Lhs, const DataT & Rhs) { \
307
+ friend std::enable_if_t < \
308
+ (Num != 1 ) && (is_op_available_for_type<FUNCTOR, T>), vec_t &> \
309
+ operator OPASSIGN (vec_t & Lhs, const DataT & Rhs) { \
262
310
Lhs = Lhs BINOP vec_t (Rhs); \
263
311
return Lhs; \
264
312
}
@@ -277,55 +325,58 @@ class vec_arith : public VecOperators<vec<DataT, NumElements>>::Combined {
277
325
#error "Undefine __SYCL_RELLOGOP macro."
278
326
#endif
279
327
280
- #define __SYCL_RELLOGOP (RELLOGOP, COND, FUNCTOR ) \
328
+ #define __SYCL_RELLOGOP (RELLOGOP, FUNCTOR ) \
281
329
template <typename T = DataT> \
282
- friend std::enable_if_t <(COND), vec<ocl_t , NumElements>> operator RELLOGOP ( \
283
- const vec_t & Lhs, const vec_t & Rhs) { \
330
+ friend std::enable_if_t <is_op_available_for_type<FUNCTOR, T>, \
331
+ vec<ocl_t , NumElements>> \
332
+ operator RELLOGOP (const vec_t & Lhs, const vec_t & Rhs) { \
284
333
return VecOperators<vec_t >::template apply<FUNCTOR>(Lhs, Rhs); \
285
334
} \
286
335
\
287
336
template <typename T = DataT> \
288
- friend std::enable_if_t <(COND), vec<ocl_t , NumElements>> operator RELLOGOP ( \
289
- const vec_t & Lhs, const DataT & Rhs) { \
337
+ friend std::enable_if_t <is_op_available_for_type<FUNCTOR, T>, \
338
+ vec<ocl_t , NumElements>> \
339
+ operator RELLOGOP (const vec_t & Lhs, const DataT & Rhs) { \
290
340
return Lhs RELLOGOP vec_t (Rhs); \
291
341
} \
292
342
template <typename T = DataT> \
293
- friend std::enable_if_t <(COND), vec<ocl_t , NumElements>> operator RELLOGOP ( \
294
- const DataT & Lhs, const vec_t & Rhs) { \
343
+ friend std::enable_if_t <is_op_available_for_type<FUNCTOR, T>, \
344
+ vec<ocl_t , NumElements>> \
345
+ operator RELLOGOP (const DataT & Lhs, const vec_t & Rhs) { \
295
346
return vec_t (Lhs) RELLOGOP Rhs; \
296
347
}
297
348
298
349
// OP is: ==, !=, <, >, <=, >=, &&, ||
299
350
// vec<RET, NumElements> operatorOP(const vec<DataT, NumElements> &Rhs) const;
300
351
// vec<RET, NumElements> operatorOP(const DataT &Rhs) const;
301
- __SYCL_RELLOGOP (==, true , std::equal_to<void >)
302
- __SYCL_RELLOGOP (!=, true , std::not_equal_to<void >)
303
- __SYCL_RELLOGOP (>, true , std::greater<void >)
304
- __SYCL_RELLOGOP (<, true , std::less<void >)
305
- __SYCL_RELLOGOP (>=, true , std::greater_equal<void >)
306
- __SYCL_RELLOGOP (<=, true , std::less_equal<void >)
352
+ __SYCL_RELLOGOP (==, std::equal_to<void >)
353
+ __SYCL_RELLOGOP (!=, std::not_equal_to<void >)
354
+ __SYCL_RELLOGOP (>, std::greater<void >)
355
+ __SYCL_RELLOGOP (<, std::less<void >)
356
+ __SYCL_RELLOGOP (>=, std::greater_equal<void >)
357
+ __SYCL_RELLOGOP (<=, std::less_equal<void >)
307
358
308
359
// Only available to integral types.
309
- __SYCL_RELLOGOP (&&, (!detail::is_vgenfloat_v<T>), std::logical_and<void >)
310
- __SYCL_RELLOGOP (||, (!detail::is_vgenfloat_v<T>), std::logical_or<void >)
360
+ __SYCL_RELLOGOP (&&, std::logical_and<void >)
361
+ __SYCL_RELLOGOP (||, std::logical_or<void >)
311
362
#undef __SYCL_RELLOGOP
312
363
#undef RELLOGOP_BASE
313
364
314
365
// Binary operations on sycl::vec<> for all types except std::byte.
315
- __SYCL_BINOP (+, +=, true , std::plus<void >)
316
- __SYCL_BINOP (-, -=, true , std::minus<void >)
317
- __SYCL_BINOP (*, *=, true , std::multiplies<void >)
318
- __SYCL_BINOP (/, /=, true , std::divides<void >)
366
+ __SYCL_BINOP (+, +=, std::plus<void >)
367
+ __SYCL_BINOP (-, -=, std::minus<void >)
368
+ __SYCL_BINOP (*, *=, std::multiplies<void >)
369
+ __SYCL_BINOP (/, /=, std::divides<void >)
319
370
320
371
// The following OPs are available only when: DataT != cl_float &&
321
372
// DataT != cl_double && DataT != cl_half && DataT != BF16.
322
- __SYCL_BINOP (%, %=, (!detail::is_vgenfloat_v<T>), std::modulus<void >)
373
+ __SYCL_BINOP (%, %=, std::modulus<void >)
323
374
// Bitwise operations are allowed for std::byte.
324
- __SYCL_BINOP (|, |=, (!detail::is_vgenfloat_v<DataT>), std::bit_or<void >)
325
- __SYCL_BINOP (&, &=, (!detail::is_vgenfloat_v<DataT>), std::bit_and<void >)
326
- __SYCL_BINOP (^, ^=, (!detail::is_vgenfloat_v<DataT>), std::bit_xor<void >)
327
- __SYCL_BINOP (>>, >>=, (!detail::is_vgenfloat_v<DataT>), ShiftRight)
328
- __SYCL_BINOP (<<, <<=, (!detail::is_vgenfloat_v<DataT>), ShiftLeft)
375
+ __SYCL_BINOP (|, |=, std::bit_or<void >)
376
+ __SYCL_BINOP (&, &=, std::bit_and<void >)
377
+ __SYCL_BINOP (^, ^=, std::bit_xor<void >)
378
+ __SYCL_BINOP (>>, >>=, ShiftRight)
379
+ __SYCL_BINOP (<<, <<=, ShiftLeft)
329
380
330
381
// friends
331
382
template <typename T1, int T2> friend class __SYCL_EBO vec;
@@ -376,9 +427,9 @@ class vec_arith<std::byte, NumElements>
376
427
return Lhs;
377
428
}
378
429
379
- __SYCL_BINOP (|, |=, true , std::bit_or<void >)
380
- __SYCL_BINOP (&, &=, true , std::bit_and<void >)
381
- __SYCL_BINOP (^, ^=, true , std::bit_xor<void >)
430
+ __SYCL_BINOP (|, |=, std::bit_or<void >)
431
+ __SYCL_BINOP (&, &=, std::bit_and<void >)
432
+ __SYCL_BINOP (^, ^=, std::bit_xor<void >)
382
433
383
434
// friends
384
435
template <typename T1, int T2> friend class __SYCL_EBO vec;
0 commit comments