3 #include "core/cl/include.h" 5 #include "utilities/foldl.h" 10 #include <type_traits> 15 #define CL_UNIT(cl_type) \ 16 struct cl_type##1 final { \ 20 #define CL_FOR_EACH_TYPE(macro) \ 21 macro(cl_char) macro(cl_uchar) macro(cl_short) macro(cl_ushort) \ 22 macro(cl_int) macro(cl_uint) macro(cl_long) macro(cl_ulong) \ 23 macro(cl_float) macro(cl_double) 25 CL_FOR_EACH_TYPE(CL_UNIT)
29 #define CL_VECTOR_REGISTER_PREFIX(macro, cl_type_prefix_) \ 30 macro(cl_type_prefix_##1) macro(cl_type_prefix_##2) \ 31 macro(cl_type_prefix_##4) macro(cl_type_prefix_##8) \ 32 macro(cl_type_prefix_##16) 34 #define CL_VECTOR_REGISTER(macro) \ 35 CL_VECTOR_REGISTER_PREFIX(macro, cl_char) \ 36 CL_VECTOR_REGISTER_PREFIX(macro, cl_uchar) \ 37 CL_VECTOR_REGISTER_PREFIX(macro, cl_short) \ 38 CL_VECTOR_REGISTER_PREFIX(macro, cl_ushort) \ 39 CL_VECTOR_REGISTER_PREFIX(macro, cl_int) \ 40 CL_VECTOR_REGISTER_PREFIX(macro, cl_uint) \ 41 CL_VECTOR_REGISTER_PREFIX(macro, cl_long) \ 42 CL_VECTOR_REGISTER_PREFIX(macro, cl_ulong) \ 43 CL_VECTOR_REGISTER_PREFIX(macro, cl_float) \ 44 CL_VECTOR_REGISTER_PREFIX(macro, cl_double) 52 using is_vector_type = std::false_type;
54 using components = std::integral_constant<size_t, 1>;
57 #define DEFINE_CL_VECTOR_TYPE_TRAIT(cl_type) \ 59 struct cl_vector_type_trait<cl_type> final { \ 60 using is_vector_type = std::true_type; \ 61 using array_type = decltype(std::declval<cl_type>().s); \ 62 static_assert(std::rank<array_type>::value == 1, \ 63 "vector types have array rank 1"); \ 64 using value_type = std::remove_all_extents_t<array_type>; \ 66 std::integral_constant<size_t, \ 67 std::extent<array_type, 0>::value>; \ 70 CL_VECTOR_REGISTER(DEFINE_CL_VECTOR_TYPE_TRAIT)
73 using is_vector_type_t =
typename cl_vector_type_trait<T>::is_vector_type;
76 constexpr
auto is_vector_type_v = is_vector_type_t<T>{};
78 template <
typename T,
typename U =
void>
79 using enable_if_is_vector_t = std::enable_if_t<is_vector_type_v<T>, U>;
81 template <
typename T,
typename U =
void>
82 using enable_if_is_not_vector_t = std::enable_if_t<!is_vector_type_v<T>, U>;
85 using components_t =
typename cl_vector_type_trait<T>::components;
88 constexpr
auto components_v = components_t<T>{};
91 using value_type_t =
typename cl_vector_type_trait<T>::value_type;
93 template <
typename...>
96 template <
typename... Ts>
97 constexpr
auto any_v =
any<Ts...>::value;
101 static constexpr
auto value = T::value;
104 template <
typename T,
typename... Ts>
105 struct any<T, Ts...> final {
106 static constexpr
auto value = any_v<T> || any_v<Ts...>;
109 template <
typename U,
typename... Ts>
110 using enable_if_any_is_vector_t =
111 std::enable_if_t<any_v<is_vector_type_t<Ts>...>, U>;
115 template <
typename T,
size_t N>
118 #define DEFINE_CL_VECTOR_CONSTRUCTOR_TRAIT(cl_type) \ 120 struct cl_vector_constructor<value_type_t<cl_type>, components_v<cl_type>> \ 122 using type = cl_type; \ 125 CL_VECTOR_REGISTER(DEFINE_CL_VECTOR_CONSTRUCTOR_TRAIT)
127 template <typename T,
size_t N>
132 using type = cl_vector_constructor_t<cl_char, N>;
135 template <
typename T,
typename Op, enable_if_is_vector_t<T,
int> = 0>
136 constexpr
auto accumulate(
const T& t,
const Op& op) {
137 return util::foldl(op, t.s);
140 template <
typename T,
141 typename Accumulator,
143 enable_if_is_vector_t<T, int> = 0>
144 constexpr
auto accumulate(
const T& t,
145 const Accumulator& accumulator,
147 return util::foldl(op, accumulator, t.s);
150 template <
typename T,
typename U,
typename Op,
size_t... Ix>
151 constexpr
auto& inplace_zip_both_vector(T& t,
154 std::index_sequence<Ix...>) {
155 return t = T{{
static_cast<value_type_t<T>
>(op(t.s[Ix], u.s[Ix]))...}};
158 template <
typename T,
161 enable_if_is_vector_t<U, int> = 0>
162 constexpr
auto& inplace_zip(T& t,
const U& u,
const Op& op) {
163 return inplace_zip_both_vector(
164 t, u, op, std::make_index_sequence<components_v<T>>{});
167 template <
typename T,
typename U,
typename Op,
size_t... Ix>
168 constexpr
auto& inplace_zip_one_vector(T& t,
171 std::index_sequence<Ix...>) {
172 return t = T{{
static_cast<value_type_t<T>
>(op(t.s[Ix], u))...}};
175 template <
typename T,
178 enable_if_is_not_vector_t<U, int> = 0>
179 constexpr
auto& inplace_zip(T& t,
const U& u,
const Op& op) {
180 return inplace_zip_one_vector(
181 t, u, op, std::make_index_sequence<components_v<T>>{});
184 template <
typename T,
typename U,
typename Op,
size_t... Ix>
185 constexpr
auto zip_both_vector(
const T& t,
188 std::index_sequence<Ix...>) {
189 using value_type = std::decay_t<decltype(op(t.s[0], u.s[0]))>;
190 return cl_vector_constructor_t<value_type,
sizeof...(Ix)>{
191 {op(t.s[Ix], u.s[Ix])...}};
194 template <
typename T,
197 std::enable_if_t<is_vector_type_v<T> && is_vector_type_v<U> &&
198 components_v<T> == components_v<U>,
200 constexpr
auto zip(
const T& t,
const U& u,
const Op& op) {
201 return zip_both_vector(
202 t, u, op, std::make_index_sequence<components_v<T>>{});
205 template <
typename T,
typename U,
typename Op,
size_t... Ix>
206 constexpr
auto zip_first_vector(
const T& t,
209 std::index_sequence<Ix...>) {
210 using value_type = std::decay_t<decltype(op(t.s[0], u))>;
211 return cl_vector_constructor_t<value_type,
sizeof...(Ix)>{
212 {op(t.s[Ix], u)...}};
219 std::enable_if_t<is_vector_type_v<T> && !is_vector_type_v<U>,
int> = 0>
220 constexpr
auto zip(
const T& t,
const U& u,
const Op& op) {
221 return zip_first_vector(
222 t, u, op, std::make_index_sequence<components_v<T>>{});
225 template <
typename T,
typename U,
typename Op,
size_t... Ix>
226 constexpr
auto zip_second_vector(
const T& t,
229 std::index_sequence<Ix...>) {
230 using value_type = std::decay_t<decltype(op(t, u.s[0]))>;
231 return cl_vector_constructor_t<value_type,
sizeof...(Ix)>{
232 {op(t, u.s[Ix])...}};
239 std::enable_if_t<!is_vector_type_v<T> && is_vector_type_v<U>,
int> = 0>
240 constexpr
auto zip(
const T& t,
const U& u,
const Op& op) {
241 return zip_second_vector(
242 t, u, op, std::make_index_sequence<components_v<U>>{});
245 template <
typename T,
typename Op,
size_t... Ix>
246 constexpr
auto map_impl(
const T& t,
const Op& op, std::index_sequence<Ix...>) {
247 using value_type = std::decay_t<decltype(op(t.s[0]))>;
248 return cl_vector_constructor_t<value_type,
sizeof...(Ix)>{{op(t.s[Ix])...}};
251 template <
typename T,
typename Op, enable_if_is_vector_t<T,
int> = 0>
252 constexpr
auto map(
const T& t,
const Op& op) {
253 return map_impl(t, op, std::make_index_sequence<components_v<T>>{});
260 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
261 constexpr
auto sum(
const T& t) {
262 return detail::accumulate(t, std::plus<>{});
265 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
266 constexpr
auto product(
const T& t) {
267 return detail::accumulate(t, std::multiplies<>{});
270 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
271 constexpr
auto mean(
const T& t) {
272 return sum(t) / detail::components_v<T>;
277 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
278 constexpr
bool all(
const T& t) {
279 return detail::accumulate(t, std::logical_and<>{});
282 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
283 constexpr
bool any(
const T& t) {
284 return detail::accumulate(t, std::logical_or<>{});
290 template <
typename T>
291 constexpr
const auto& operator()(
const T& a,
const T& b)
const {
298 template <
typename T>
299 constexpr
const auto& operator()(
const T& a,
const T& b)
const {
307 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
308 constexpr
auto min_element(
const T& t) {
312 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
313 constexpr
auto max_element(
const T& t) {
319 template <
typename T,
320 size_t components = detail::components_v<T>,
321 detail::enable_if_is_vector_t<T, int> = 0>
322 constexpr
auto isnan(
const T& t) {
323 return detail::map(t, [](
auto i) {
return std::isnan(i); });
326 template <
typename T,
327 size_t components = detail::components_v<T>,
328 detail::enable_if_is_vector_t<T, int> = 0>
329 constexpr
auto isinf(
const T& t) {
330 return detail::map(t, [](
auto i) {
return std::isinf(i); });
333 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
334 inline auto sqrt(
const T& t) {
335 return detail::map(t, [](
auto i) {
return std::sqrt(i); });
338 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
339 inline auto log(
const T& t) {
340 return detail::map(t, [](
auto i) {
return std::log(i); });
343 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
344 inline auto abs(
const T& t) {
345 return detail::map(t, [](
auto i) {
return std::abs(i); });
348 template <
typename T,
350 detail::enable_if_any_is_vector_t<int, T, U> = 0>
351 inline auto copysign(
const T& t,
const U& u) {
353 t, u, [](
auto i,
auto j) {
return std::copysign(i, j); });
356 template <
typename T,
358 detail::enable_if_any_is_vector_t<int, T, U> = 0>
359 inline auto pow(
const T& t,
const U& u) {
360 return detail::zip(t, u, [](
auto i,
auto j) {
return std::pow(i, j); });
363 template <
typename T,
365 detail::enable_if_any_is_vector_t<int, T, U> = 0>
366 inline auto max(
const T& t,
const U& u) {
370 template <
typename T,
372 detail::enable_if_any_is_vector_t<int, T, U> = 0>
373 inline auto min(
const T& t,
const U& u) {
377 template <
size_t Components,
typename Input>
378 constexpr
auto construct_vector(Input input) {
379 detail::cl_vector_constructor_t<Input, Components> ret{};
380 for (
auto& i : ret.s) {
388 template <
typename T,
390 detail::enable_if_any_is_vector_t<int, T, U> = 0>
391 constexpr
auto operator==(
const T& a,
const U& b) {
392 return detail::accumulate(detail::zip(a, b, std::equal_to<>{}),
393 std::logical_and<>{});
396 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
397 constexpr
auto operator!(
const T& a) {
398 return detail::map(a, std::logical_not<>{});
401 template <
typename T,
403 detail::enable_if_any_is_vector_t<int, T, U> = 0>
404 constexpr
auto operator!=(
const T& a,
const U& b) {
408 template <
typename T,
410 detail::enable_if_any_is_vector_t<int, T, U> = 0>
411 constexpr
auto operator<(
const T& a,
const U& b) {
412 return detail::zip(a, b, std::less<>{});
415 template <
typename T,
417 detail::enable_if_any_is_vector_t<int, T, U> = 0>
418 constexpr
auto operator<=(
const T& a,
const U& b) {
419 return detail::zip(a, b, std::less_equal<>{});
424 template <
typename T,
typename U, detail::enable_if_is_vector_t<T,
int> = 0>
425 constexpr
auto& operator+=(T& a,
const U& b) {
426 return detail::inplace_zip(a, b, std::plus<>{});
429 template <
typename T,
typename U, detail::enable_if_is_vector_t<T,
int> = 0>
430 constexpr
auto& operator-=(T& a,
const U& b) {
431 return detail::inplace_zip(a, b, std::minus<>{});
434 template <
typename T,
typename U, detail::enable_if_is_vector_t<T,
int> = 0>
435 constexpr
auto& operator*=(T& a,
const U& b) {
436 return detail::inplace_zip(a, b, std::multiplies<>{});
439 template <
typename T,
typename U, detail::enable_if_is_vector_t<T,
int> = 0>
440 constexpr
auto& operator/=(T& a,
const U& b) {
441 return detail::inplace_zip(a, b, std::divides<>{});
444 template <
typename T,
typename U, detail::enable_if_is_vector_t<T,
int> = 0>
445 constexpr
auto& operator%=(T& a,
const U& b) {
446 return detail::inplace_zip(a, b, std::modulus<>{});
451 template <
typename T,
453 detail::enable_if_any_is_vector_t<int, T, U> = 0>
454 constexpr
auto operator+(
const T& a,
const U& b) {
455 return detail::zip(a, b, std::plus<>{});
458 template <
typename T,
460 detail::enable_if_any_is_vector_t<int, T, U> = 0>
461 constexpr
auto operator-(
const T& a,
const U& b) {
462 return detail::zip(a, b, std::minus<>{});
465 template <
typename T,
467 detail::enable_if_any_is_vector_t<int, T, U> = 0>
468 constexpr
auto operator*(
const T& a,
const U& b) {
469 return detail::zip(a, b, std::multiplies<>{});
472 template <
typename T,
474 detail::enable_if_any_is_vector_t<int, T, U> = 0>
475 constexpr
auto operator/(
const T& a,
const U& b) {
476 return detail::zip(a, b, std::divides<>{});
479 template <
typename T,
481 detail::enable_if_any_is_vector_t<int, T, U> = 0>
482 constexpr
auto operator%(
const T& a,
const U& b) {
483 return detail::zip(a, b, std::modulus<>{});
486 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
487 constexpr
auto operator+(
const T& a) {
491 template <
typename T, detail::enable_if_is_vector_t<T,
int> = 0>
492 constexpr
auto operator-(
const T& a) {
493 return detail::map(a, std::negate<>{});