@@ -186,51 +186,26 @@ class __SYCL_EBO vec
186
186
std::false_type> {};
187
187
188
188
// Utility trait for creating an std::array from an vector argument.
189
- template <typename DataT_, typename T, std::size_t ... Is>
190
- static constexpr std::array<DataT_, sizeof ...(Is)>
191
- VecToArray (const vec<T, sizeof ...(Is)> &V, std::index_sequence<Is...>) {
192
- return {static_cast <DataT_>(V[Is])...};
193
- }
194
- template <typename DataT_, typename T, int N, typename T2, typename T3,
195
- template <typename > class T4 , int ... T5, std::size_t ... Is>
196
- static constexpr std::array<DataT_, sizeof ...(Is)>
197
- VecToArray (const detail::SwizzleOp<vec<T, N>, T2, T3, T4, T5...> &V,
198
- std::index_sequence<Is...>) {
199
- return {static_cast <DataT_>(V.getValue (Is))...};
200
- }
201
- template <typename DataT_, typename T, int N, typename T2, typename T3,
202
- template <typename > class T4 , int ... T5, std::size_t ... Is>
203
- static constexpr std::array<DataT_, sizeof ...(Is)>
204
- VecToArray (const detail::SwizzleOp<const vec<T, N>, T2, T3, T4, T5...> &V,
205
- std::index_sequence<Is...>) {
206
- return {static_cast <DataT_>(V.getValue (Is))...};
207
- }
208
- template <typename DataT_, typename T, int N>
209
- static constexpr std::array<DataT_, N>
210
- FlattenVecArgHelper (const vec<T, N> &A) {
211
- return VecToArray<DataT_>(A, std::make_index_sequence<N>());
212
- }
213
- template <typename DataT_, typename T, int N, typename T2, typename T3,
214
- template <typename > class T4 , int ... T5>
215
- static constexpr std::array<DataT_, sizeof ...(T5)> FlattenVecArgHelper (
216
- const detail::SwizzleOp<vec<T, N>, T2, T3, T4, T5...> &A) {
217
- return VecToArray<DataT_>(A, std::make_index_sequence<sizeof ...(T5)>());
218
- }
219
- template <typename DataT_, typename T, int N, typename T2, typename T3,
220
- template <typename > class T4 , int ... T5>
221
- static constexpr std::array<DataT_, sizeof ...(T5)> FlattenVecArgHelper (
222
- const detail::SwizzleOp<const vec<T, N>, T2, T3, T4, T5...> &A) {
223
- return VecToArray<DataT_>(A, std::make_index_sequence<sizeof ...(T5)>());
224
- }
225
- template <typename DataT_, typename T>
226
- static constexpr auto FlattenVecArgHelper (const T &A) {
227
- // static_cast required to avoid narrowing conversion warning
228
- // when T = unsigned long int and DataT_ = int.
229
- return std::array<DataT_, 1 >{static_cast <DataT_>(A)};
230
- }
231
- template <typename DataT_, typename T> struct FlattenVecArg {
189
+ template <typename DataT_, typename T> class FlattenVecArg {
190
+ template <std::size_t ... Is>
191
+ static constexpr auto helper (const T &V, std::index_sequence<Is...>) {
192
+ // FIXME: Swizzle's `operator[]` for expression trees seems to be broken
193
+ // and returns values of the underlying vector of some of the operands. On
194
+ // the other hand, `getValue()` gives correct results. This can be changed
195
+ // to using `operator[]` once the bug is fixed.
196
+ if constexpr (detail::is_swizzle_v<T>)
197
+ return std::array{static_cast <DataT_>(V.getValue (Is))...};
198
+ else
199
+ return std::array{static_cast <DataT_>(V[Is])...};
200
+ }
201
+
202
+ public:
232
203
constexpr auto operator ()(const T &A) const {
233
- return FlattenVecArgHelper<DataT_>(A);
204
+ if constexpr (detail::is_vec_or_swizzle_v<T>) {
205
+ return helper (A, std::make_index_sequence<T ::size ()>());
206
+ } else {
207
+ return std::array{static_cast <DataT_>(A)};
208
+ }
234
209
}
235
210
};
236
211
@@ -239,69 +214,6 @@ class __SYCL_EBO vec
239
214
using VecArgArrayCreator =
240
215
detail::ArrayCreator<DataT_, FlattenVecArg, ArgTN...>;
241
216
242
- #define __SYCL_ALLOW_VECTOR_SIZES (num_elements ) \
243
- template <int Counter, int MaxValue, typename DataT_, class ... tail> \
244
- struct SizeChecker <Counter, MaxValue, vec<DataT_, num_elements>, tail...> \
245
- : std::conditional_t < \
246
- Counter + (num_elements) <= MaxValue, \
247
- SizeChecker<Counter + (num_elements), MaxValue, tail...>, \
248
- std::false_type> {}; \
249
- template <int Counter, int MaxValue, typename DataT_, typename T2, \
250
- typename T3, template <typename > class T4 , int ... T5, \
251
- class ... tail> \
252
- struct SizeChecker < \
253
- Counter, MaxValue, \
254
- detail::SwizzleOp<vec<DataT_, num_elements>, T2, T3, T4, T5...>, \
255
- tail...> \
256
- : std::conditional_t < \
257
- Counter + sizeof ...(T5) <= MaxValue, \
258
- SizeChecker<Counter + sizeof ...(T5), MaxValue, tail...>, \
259
- std::false_type> {}; \
260
- template <int Counter, int MaxValue, typename DataT_, typename T2, \
261
- typename T3, template <typename > class T4 , int ... T5, \
262
- class ... tail> \
263
- struct SizeChecker < \
264
- Counter, MaxValue, \
265
- detail::SwizzleOp<const vec<DataT_, num_elements>, T2, T3, T4, T5...>, \
266
- tail...> \
267
- : std::conditional_t < \
268
- Counter + sizeof ...(T5) <= MaxValue, \
269
- SizeChecker<Counter + sizeof ...(T5), MaxValue, tail...>, \
270
- std::false_type> {};
271
-
272
- __SYCL_ALLOW_VECTOR_SIZES (1 )
273
- __SYCL_ALLOW_VECTOR_SIZES(2 )
274
- __SYCL_ALLOW_VECTOR_SIZES(3 )
275
- __SYCL_ALLOW_VECTOR_SIZES(4 )
276
- __SYCL_ALLOW_VECTOR_SIZES(8 )
277
- __SYCL_ALLOW_VECTOR_SIZES(16 )
278
- #undef __SYCL_ALLOW_VECTOR_SIZES
279
-
280
- // TypeChecker is needed for vec(const argTN &... args) ctor to validate args.
281
- template <typename T, typename DataT_>
282
- struct TypeChecker : std::is_convertible<T, DataT_> {};
283
- #define __SYCL_ALLOW_VECTOR_TYPES (num_elements ) \
284
- template <typename DataT_> \
285
- struct TypeChecker <vec<DataT_, num_elements>, DataT_> : std::true_type {}; \
286
- template <typename DataT_, typename T2, typename T3, \
287
- template <typename > class T4 , int ... T5> \
288
- struct TypeChecker < \
289
- detail::SwizzleOp<vec<DataT_, num_elements>, T2, T3, T4, T5...>, DataT_> \
290
- : std::true_type {}; \
291
- template <typename DataT_, typename T2, typename T3, \
292
- template <typename > class T4 , int ... T5> \
293
- struct TypeChecker < \
294
- detail::SwizzleOp<const vec<DataT_, num_elements>, T2, T3, T4, T5...>, \
295
- DataT_> : std::true_type {};
296
-
297
- __SYCL_ALLOW_VECTOR_TYPES (1 )
298
- __SYCL_ALLOW_VECTOR_TYPES(2 )
299
- __SYCL_ALLOW_VECTOR_TYPES(3 )
300
- __SYCL_ALLOW_VECTOR_TYPES(4 )
301
- __SYCL_ALLOW_VECTOR_TYPES(8 )
302
- __SYCL_ALLOW_VECTOR_TYPES(16 )
303
- #undef __SYCL_ALLOW_VECTOR_TYPES
304
-
305
217
template <int ... Indexes>
306
218
using Swizzle =
307
219
detail::SwizzleOp<vec, detail::GetOp<DataT>, detail::GetOp<DataT>,
@@ -313,13 +225,25 @@ class __SYCL_EBO vec
313
225
detail::GetOp, Indexes...>;
314
226
315
227
// Shortcuts for args validation in vec(const argTN &... args) ctor.
316
- template <typename ... argTN>
317
- using EnableIfSuitableTypes = typename std::enable_if_t <
318
- std::conjunction_v<TypeChecker<argTN, DataT>...>>;
228
+ template <typename CtorArgTy>
229
+ static constexpr bool AllowArgTypeInVariadicCtor = []() constexpr {
230
+ // FIXME: This logic implements the behavior of the previous implementation.
231
+ if constexpr (detail::is_vec_or_swizzle_v<CtorArgTy>) {
232
+ if constexpr (CtorArgTy::size () == 1 )
233
+ return std::is_convertible_v<typename CtorArgTy::element_type, DataT>;
234
+ else
235
+ return std::is_same_v<typename CtorArgTy::element_type, DataT>;
236
+ } else {
237
+ return std::is_convertible_v<CtorArgTy, DataT>;
238
+ }
239
+ }();
319
240
320
- template <typename ... argTN>
321
- using EnableIfSuitableNumElements =
322
- typename std::enable_if_t <SizeChecker<0 , NumElements, argTN...>::value>;
241
+ template <typename T> static constexpr int num_elements () {
242
+ if constexpr (detail::is_vec_or_swizzle_v<T>)
243
+ return T::size ();
244
+ else
245
+ return 1 ;
246
+ }
323
247
324
248
// Element type for relational operator return value.
325
249
using rel_t = detail::select_cl_scalar_integral_signed_t <DataT>;
@@ -349,8 +273,10 @@ class __SYCL_EBO vec
349
273
350
274
// Constructor from values of base type or vec of base type. Checks that
351
275
// base types are match and that the NumElements == sum of lengths of args.
352
- template <typename ... argTN, typename = EnableIfSuitableTypes<argTN...>,
353
- typename = EnableIfSuitableNumElements<argTN...>>
276
+ template <typename ... argTN,
277
+ typename = std::enable_if_t <
278
+ ((AllowArgTypeInVariadicCtor<argTN> && ...)) &&
279
+ ((num_elements<argTN>() + ...)) == NumElements>>
354
280
constexpr vec (const argTN &...args)
355
281
: vec{VecArgArrayCreator<DataT, argTN...>::Create (args...),
356
282
std::make_index_sequence<NumElements>()} {}
0 commit comments