DPC++ Runtime
Runtime libraries for oneAPI DPC++
known_identity.hpp
Go to the documentation of this file.
1 //==----------- known_identity.hpp -----------------------------------------==//
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 <sycl/aliases.hpp> // for half
12 #include <sycl/detail/generic_type_traits.hpp> // for is_genbool, is_genint...
13 #include <sycl/functional.hpp> // for bit_and, bit_or, bit_xor
14 #include <sycl/half_type.hpp> // for half
15 #include <sycl/marray.hpp> // for marray
16 #include <sycl/types.hpp> // for vec
17 
18 #include <cstddef> // for byte, size_t
19 #include <functional> // for logical_and, logical_or
20 #include <limits> // for numeric_limits
21 #include <stdint.h> // for uint16_t
22 #include <type_traits> // for enable_if_t, bool_con...
23 
24 namespace sycl {
25 inline namespace _V1 {
26 namespace detail {
27 
28 template <typename T, class BinaryOperation>
29 using IsPlus =
30  std::bool_constant<std::is_same_v<BinaryOperation, sycl::plus<T>> ||
31  std::is_same_v<BinaryOperation, sycl::plus<void>>>;
32 
33 template <typename T, class BinaryOperation>
34 using IsMultiplies =
35  std::bool_constant<std::is_same_v<BinaryOperation, sycl::multiplies<T>> ||
36  std::is_same_v<BinaryOperation, sycl::multiplies<void>>>;
37 
38 template <typename T, class BinaryOperation>
39 using IsMinimum =
40  std::bool_constant<std::is_same_v<BinaryOperation, sycl::minimum<T>> ||
41  std::is_same_v<BinaryOperation, sycl::minimum<void>>>;
42 
43 template <typename T, class BinaryOperation>
44 using IsMaximum =
45  std::bool_constant<std::is_same_v<BinaryOperation, sycl::maximum<T>> ||
46  std::is_same_v<BinaryOperation, sycl::maximum<void>>>;
47 
48 template <typename T, class BinaryOperation>
49 using IsBitAND =
50  std::bool_constant<std::is_same_v<BinaryOperation, sycl::bit_and<T>> ||
51  std::is_same_v<BinaryOperation, sycl::bit_and<void>>>;
52 
53 template <typename T, class BinaryOperation>
54 using IsBitOR =
55  std::bool_constant<std::is_same_v<BinaryOperation, sycl::bit_or<T>> ||
56  std::is_same_v<BinaryOperation, sycl::bit_or<void>>>;
57 
58 template <typename T, class BinaryOperation>
59 using IsBitXOR =
60  std::bool_constant<std::is_same_v<BinaryOperation, sycl::bit_xor<T>> ||
61  std::is_same_v<BinaryOperation, sycl::bit_xor<void>>>;
62 
63 template <typename T, class BinaryOperation>
64 using IsLogicalAND = std::bool_constant<
65  std::is_same_v<BinaryOperation, std::logical_and<T>> ||
66  std::is_same_v<BinaryOperation, std::logical_and<void>> ||
67  std::is_same_v<BinaryOperation, sycl::logical_and<T>> ||
68  std::is_same_v<BinaryOperation, sycl::logical_and<void>>>;
69 
70 template <typename T, class BinaryOperation>
71 using IsLogicalOR =
72  std::bool_constant<std::is_same_v<BinaryOperation, std::logical_or<T>> ||
73  std::is_same_v<BinaryOperation, std::logical_or<void>> ||
74  std::is_same_v<BinaryOperation, sycl::logical_or<T>> ||
75  std::is_same_v<BinaryOperation, sycl::logical_or<void>>>;
76 
77 // Use SFINAE so that the "true" branch could be implemented in
78 // include/sycl/stl_wrappers/complex that would only be available if STL's
79 // <complex> is included by users.
80 template <typename T, typename = void>
81 struct isComplex : public std::false_type {};
82 
83 // Identity = 0
84 template <typename T, class BinaryOperation>
85 using IsZeroIdentityOp = std::bool_constant<
86  ((is_genbool_v<T> ||
87  is_geninteger_v<T>)&&(IsPlus<T, BinaryOperation>::value ||
90  (is_genfloat_v<T> && IsPlus<T, BinaryOperation>::value) ||
92 
93 // Identity = 1
94 template <typename T, class BinaryOperation>
95 using IsOneIdentityOp = std::bool_constant<(
96  is_genbool_v<T> || is_geninteger_v<T> ||
97  is_genfloat_v<T>)&&IsMultiplies<T, BinaryOperation>::value>;
98 
99 // Identity = ~0
100 template <typename T, class BinaryOperation>
101 using IsOnesIdentityOp = std::bool_constant<(
102  is_genbool_v<T> ||
103  is_geninteger_v<T>)&&IsBitAND<T, BinaryOperation>::value>;
104 
105 // Identity = <max possible value>
106 template <typename T, class BinaryOperation>
107 using IsMinimumIdentityOp = std::bool_constant<(
108  is_genbool_v<T> || is_geninteger_v<T> ||
109  is_genfloat_v<T>)&&IsMinimum<T, BinaryOperation>::value>;
110 
111 // Identity = <min possible value>
112 template <typename T, class BinaryOperation>
113 using IsMaximumIdentityOp = std::bool_constant<(
114  is_genbool_v<T> || is_geninteger_v<T> ||
115  is_genfloat_v<T>)&&IsMaximum<T, BinaryOperation>::value>;
116 
117 // Identity = false
118 template <typename T, class BinaryOperation>
120  std::bool_constant<IsLogicalOR<T, BinaryOperation>::value>;
121 
122 // Identity = true
123 template <typename T, class BinaryOperation>
125  std::bool_constant<IsLogicalAND<T, BinaryOperation>::value>;
126 
127 template <typename T, class BinaryOperation>
129  std::bool_constant<IsZeroIdentityOp<T, BinaryOperation>::value ||
136 
137 template <typename BinaryOperation, typename AccumulatorT>
139  : std::integral_constant<
140  bool, IsKnownIdentityOp<AccumulatorT, BinaryOperation>::value> {};
141 
142 template <typename BinaryOperation, typename AccumulatorT, typename = void>
144 
146 template <typename BinaryOperation, typename AccumulatorT>
148  BinaryOperation, AccumulatorT,
149  std::enable_if_t<IsZeroIdentityOp<AccumulatorT, BinaryOperation>::value>> {
150  static constexpr AccumulatorT value = static_cast<AccumulatorT>(0);
151 };
152 
153 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
154 template <typename BinaryOperation, int NumElements>
156  BinaryOperation, vec<std::byte, NumElements>,
157  std::enable_if_t<IsZeroIdentityOp<vec<std::byte, NumElements>,
158  BinaryOperation>::value>> {
159  static constexpr vec<std::byte, NumElements> value =
161 };
162 
163 template <typename BinaryOperation, int NumElements>
165  BinaryOperation, marray<std::byte, NumElements>,
166  std::enable_if_t<IsZeroIdentityOp<marray<std::byte, NumElements>,
167  BinaryOperation>::value>> {
168  static constexpr marray<std::byte, NumElements> value =
170 };
171 #endif
172 
173 template <typename BinaryOperation, int NumElements>
175  BinaryOperation, vec<sycl::half, NumElements>,
176  std::enable_if_t<IsZeroIdentityOp<vec<sycl::half, NumElements>,
177  BinaryOperation>::value>> {
178  static constexpr vec<sycl::half, NumElements> value =
180 };
181 
182 template <typename BinaryOperation>
184  BinaryOperation, half,
185  std::enable_if_t<IsZeroIdentityOp<half, BinaryOperation>::value>> {
186  static constexpr half value =
187 #ifdef __SYCL_DEVICE_ONLY__
188  0;
189 #else
190  sycl::detail::host_half_impl::half(static_cast<uint16_t>(0));
191 #endif
192 };
193 
195 template <typename BinaryOperation, typename AccumulatorT>
197  BinaryOperation, AccumulatorT,
198  std::enable_if_t<IsOneIdentityOp<AccumulatorT, BinaryOperation>::value>> {
199  static constexpr AccumulatorT value = static_cast<AccumulatorT>(1);
200 };
201 
202 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
203 template <typename BinaryOperation, int NumElements>
205  BinaryOperation, vec<std::byte, NumElements>,
206  std::enable_if_t<
207  IsOneIdentityOp<vec<std::byte, NumElements>, BinaryOperation>::value>> {
208  static constexpr vec<std::byte, NumElements> value =
210 };
211 
212 template <typename BinaryOperation, int NumElements>
214  BinaryOperation, marray<std::byte, NumElements>,
215  std::enable_if_t<IsOneIdentityOp<marray<std::byte, NumElements>,
216  BinaryOperation>::value>> {
217  static constexpr marray<std::byte, NumElements> value =
219 };
220 #endif
221 
222 template <typename BinaryOperation>
224  BinaryOperation, half,
225  std::enable_if_t<IsOneIdentityOp<half, BinaryOperation>::value>> {
226  static constexpr half value =
227 #ifdef __SYCL_DEVICE_ONLY__
228  1;
229 #else
230  sycl::detail::host_half_impl::half(static_cast<uint16_t>(0x3C00));
231 #endif
232 };
233 
235 template <typename BinaryOperation, typename AccumulatorT>
237  BinaryOperation, AccumulatorT,
238  std::enable_if_t<IsOnesIdentityOp<AccumulatorT, BinaryOperation>::value>> {
239  static constexpr AccumulatorT value = static_cast<AccumulatorT>(-1LL);
240 };
241 
242 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
243 template <typename BinaryOperation, int NumElements>
245  BinaryOperation, vec<std::byte, NumElements>,
246  std::enable_if_t<IsOnesIdentityOp<vec<std::byte, NumElements>,
247  BinaryOperation>::value>> {
248  static constexpr vec<std::byte, NumElements> value =
250 };
251 
252 template <typename BinaryOperation, int NumElements>
254  BinaryOperation, marray<std::byte, NumElements>,
255  std::enable_if_t<IsOnesIdentityOp<marray<std::byte, NumElements>,
256  BinaryOperation>::value>> {
257  static constexpr marray<std::byte, NumElements> value =
259 };
260 #endif
261 
263 template <typename BinaryOperation, typename AccumulatorT>
264 struct known_identity_impl<BinaryOperation, AccumulatorT,
265  std::enable_if_t<IsMinimumIdentityOp<
266  AccumulatorT, BinaryOperation>::value>> {
267  static constexpr AccumulatorT value = static_cast<AccumulatorT>(
268  std::numeric_limits<AccumulatorT>::has_infinity
269  ? std::numeric_limits<AccumulatorT>::infinity()
270  : (std::numeric_limits<AccumulatorT>::max)());
271 };
272 
273 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
274 template <typename BinaryOperation, int NumElements>
276  BinaryOperation, vec<std::byte, NumElements>,
277  std::enable_if_t<IsMinimumIdentityOp<vec<std::byte, NumElements>,
278  BinaryOperation>::value>> {
279  static constexpr vec<std::byte, NumElements> value =
280  static_cast<vec<std::byte, NumElements>>(
281  std::numeric_limits<vec<std::byte, NumElements>>::has_infinity
282  ? std::numeric_limits<vec<std::byte, NumElements>>::infinity()
283  : (std::numeric_limits<vec<std::byte, NumElements>>::max)());
284 };
285 
286 template <typename BinaryOperation, int NumElements>
288  BinaryOperation, marray<std::byte, NumElements>,
289  std::enable_if_t<IsMinimumIdentityOp<marray<std::byte, NumElements>,
290  BinaryOperation>::value>> {
291  static constexpr marray<std::byte, NumElements> value =
292  static_cast<marray<std::byte, NumElements>>(
293  std::numeric_limits<marray<std::byte, NumElements>>::has_infinity
294  ? std::numeric_limits<marray<std::byte, NumElements>>::infinity()
295  : (std::numeric_limits<marray<std::byte, NumElements>>::max)());
296 };
297 #endif
298 
300 template <typename BinaryOperation, typename AccumulatorT>
301 struct known_identity_impl<BinaryOperation, AccumulatorT,
302  std::enable_if_t<IsMaximumIdentityOp<
303  AccumulatorT, BinaryOperation>::value>> {
304  static constexpr AccumulatorT value = static_cast<AccumulatorT>(
305  std::numeric_limits<AccumulatorT>::has_infinity
306  ? static_cast<AccumulatorT>(
307  -std::numeric_limits<AccumulatorT>::infinity())
308  : std::numeric_limits<AccumulatorT>::lowest());
309 };
310 
311 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
312 template <typename BinaryOperation, int NumElements>
314  BinaryOperation, vec<std::byte, NumElements>,
315  std::enable_if_t<IsMaximumIdentityOp<vec<std::byte, NumElements>,
316  BinaryOperation>::value>> {
317  static constexpr vec<std::byte, NumElements> value = static_cast<
319  std::numeric_limits<vec<std::byte, NumElements>>::has_infinity
320  ? static_cast<vec<std::byte, NumElements>>(
321  -std::numeric_limits<vec<std::byte, NumElements>>::infinity())
322  : std::numeric_limits<vec<std::byte, NumElements>>::lowest());
323 };
324 
325 template <typename BinaryOperation, int NumElements>
327  BinaryOperation, marray<std::byte, NumElements>,
328  std::enable_if_t<IsMaximumIdentityOp<marray<std::byte, NumElements>,
329  BinaryOperation>::value>> {
330  static constexpr marray<std::byte, NumElements> value =
331  static_cast<marray<std::byte, NumElements>>(
332  std::numeric_limits<marray<std::byte, NumElements>>::has_infinity
333  ? static_cast<marray<std::byte, NumElements>>(
334  -std::numeric_limits<
335  marray<std::byte, NumElements>>::infinity())
336  : std::numeric_limits<marray<std::byte, NumElements>>::lowest());
337 };
338 #endif
339 
341 template <typename BinaryOperation, typename AccumulatorT>
343  BinaryOperation, AccumulatorT,
344  std::enable_if_t<IsFalseIdentityOp<AccumulatorT, BinaryOperation>::value>> {
345  static constexpr AccumulatorT value = static_cast<AccumulatorT>(false);
346 };
347 
348 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
349 template <typename BinaryOperation, int NumElements>
351  BinaryOperation, vec<std::byte, NumElements>,
352  std::enable_if_t<IsFalseIdentityOp<vec<std::byte, NumElements>,
353  BinaryOperation>::value>> {
354  static constexpr vec<std::byte, NumElements> value =
356 };
357 
358 template <typename BinaryOperation, size_t NumElements>
360  BinaryOperation, marray<std::byte, NumElements>,
361  std::enable_if_t<IsFalseIdentityOp<marray<std::byte, NumElements>,
362  BinaryOperation>::value>> {
363  static constexpr marray<std::byte, NumElements> value =
365 };
366 #endif
367 
369 template <typename BinaryOperation, typename AccumulatorT>
371  BinaryOperation, AccumulatorT,
372  std::enable_if_t<IsTrueIdentityOp<AccumulatorT, BinaryOperation>::value>> {
373  static constexpr AccumulatorT value = static_cast<AccumulatorT>(true);
374 };
375 
376 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
377 template <typename BinaryOperation, int NumElements>
379  BinaryOperation, vec<std::byte, NumElements>,
380  std::enable_if_t<IsTrueIdentityOp<vec<std::byte, NumElements>,
381  BinaryOperation>::value>> {
382  static constexpr vec<std::byte, NumElements> value =
384 };
385 
386 template <typename BinaryOperation, int NumElements>
388  BinaryOperation, marray<std::byte, NumElements>,
389  std::enable_if_t<IsTrueIdentityOp<marray<std::byte, NumElements>,
390  BinaryOperation>::value>> {
391  static constexpr marray<std::byte, NumElements> value =
393 };
394 #endif
395 
396 } // namespace detail
397 
398 // ---- has_known_identity
399 template <typename BinaryOperation, typename AccumulatorT>
401  : detail::has_known_identity_impl<std::decay_t<BinaryOperation>,
402  std::decay_t<AccumulatorT>> {};
403 
404 template <typename BinaryOperation, typename AccumulatorT>
405 inline constexpr bool has_known_identity_v =
407 
408 // ---- known_identity
409 template <typename BinaryOperation, typename AccumulatorT>
411  : detail::known_identity_impl<std::decay_t<BinaryOperation>,
412  std::decay_t<AccumulatorT>> {};
413 
414 template <typename BinaryOperation, typename AccumulatorT>
415 inline constexpr AccumulatorT known_identity_v =
417 
418 } // namespace _V1
419 } // namespace sycl
Provides a cross-platform math array class template that works on SYCL devices as well as in host C++...
Definition: marray.hpp:48
Provides a cross-patform vector class template that works efficiently on SYCL devices as well as in h...
Definition: types.hpp:284
std::bool_constant< IsLogicalOR< T, BinaryOperation >::value > IsFalseIdentityOp
std::bool_constant< IsLogicalAND< T, BinaryOperation >::value > IsTrueIdentityOp
std::bool_constant< std::is_same_v< BinaryOperation, sycl::maximum< T > >||std::is_same_v< BinaryOperation, sycl::maximum< void > >> IsMaximum
std::bool_constant< std::is_same_v< BinaryOperation, sycl::bit_or< T > >||std::is_same_v< BinaryOperation, sycl::bit_or< void > >> IsBitOR
std::bool_constant< IsZeroIdentityOp< T, BinaryOperation >::value||IsOneIdentityOp< T, BinaryOperation >::value||IsOnesIdentityOp< T, BinaryOperation >::value||IsMinimumIdentityOp< T, BinaryOperation >::value||IsMaximumIdentityOp< T, BinaryOperation >::value||IsFalseIdentityOp< T, BinaryOperation >::value||IsTrueIdentityOp< T, BinaryOperation >::value > IsKnownIdentityOp
std::bool_constant<(is_genbool_v< T >||is_geninteger_v< T >||is_genfloat_v< T >)&&IsMaximum< T, BinaryOperation >::value > IsMaximumIdentityOp
std::bool_constant< std::is_same_v< BinaryOperation, sycl::multiplies< T > >||std::is_same_v< BinaryOperation, sycl::multiplies< void > >> IsMultiplies
std::bool_constant< std::is_same_v< BinaryOperation, std::logical_or< T > >||std::is_same_v< BinaryOperation, std::logical_or< void > >||std::is_same_v< BinaryOperation, sycl::logical_or< T > >||std::is_same_v< BinaryOperation, sycl::logical_or< void > >> IsLogicalOR
std::bool_constant< std::is_same_v< BinaryOperation, std::logical_and< T > >||std::is_same_v< BinaryOperation, std::logical_and< void > >||std::is_same_v< BinaryOperation, sycl::logical_and< T > >||std::is_same_v< BinaryOperation, sycl::logical_and< void > >> IsLogicalAND
std::bool_constant<((is_genbool_v< T >||is_geninteger_v< T >)&&(IsPlus< T, BinaryOperation >::value||IsBitOR< T, BinaryOperation >::value||IsBitXOR< T, BinaryOperation >::value))||(is_genfloat_v< T > &&IsPlus< T, BinaryOperation >::value)||(isComplex< T >::value &&IsPlus< T, BinaryOperation >::value)> IsZeroIdentityOp
std::bool_constant<(is_genbool_v< T >||is_geninteger_v< T >||is_genfloat_v< T >)&&IsMultiplies< T, BinaryOperation >::value > IsOneIdentityOp
std::bool_constant<(is_genbool_v< T >||is_geninteger_v< T >||is_genfloat_v< T >)&&IsMinimum< T, BinaryOperation >::value > IsMinimumIdentityOp
std::bool_constant< std::is_same_v< BinaryOperation, sycl::plus< T > >||std::is_same_v< BinaryOperation, sycl::plus< void > >> IsPlus
std::bool_constant< std::is_same_v< BinaryOperation, sycl::minimum< T > >||std::is_same_v< BinaryOperation, sycl::minimum< void > >> IsMinimum
std::bool_constant< std::is_same_v< BinaryOperation, sycl::bit_and< T > >||std::is_same_v< BinaryOperation, sycl::bit_and< void > >> IsBitAND
std::bool_constant< std::is_same_v< BinaryOperation, sycl::bit_xor< T > >||std::is_same_v< BinaryOperation, sycl::bit_xor< void > >> IsBitXOR
std::bool_constant<(is_genbool_v< T >||is_geninteger_v< T >)&&IsBitAND< T, BinaryOperation >::value > IsOnesIdentityOp
constexpr bool has_known_identity_v
unsigned char byte
Definition: image.hpp:107
constexpr AccumulatorT known_identity_v
sycl::detail::half_impl::half half
Definition: aliases.hpp:101
Definition: access.hpp:18