alpaka
Abstraction Library for Parallel Kernel Acceleration
Loading...
Searching...
No Matches
math.hpp
Go to the documentation of this file.
1/* Copyright 2023 Axel Huebl, Benjamin Worpitz, Matthias Werner, Bert Wesarg, Valentin Gehrke, René Widera,
2 * Jan Stephan, Andrea Bocci, Bernhard Manfred Gruber, Jeffrey Kelling, Sergei Bastrakov, Mehmet Yusufoglu
3 * SPDX-License-Identifier: MPL-2.0
4 */
5
6#pragma once
7
8#include "alpaka/api/api.hpp"
15
16#if ALPAKA_LANG_SYCL
17
18# include <sycl/sycl.hpp>
19
20# include <concepts>
21
22namespace alpaka::math::internal
23{
24 template<typename T_Arg>
25 requires(std::is_arithmetic_v<T_Arg>)
26 struct Abs::Op<SyclMath, T_Arg>
27 {
28 constexpr auto operator()(SyclMath, T_Arg const& arg) const
29 {
30 if constexpr(std::is_integral_v<T_Arg>)
31 return sycl::abs(arg);
32 else if constexpr(std::is_floating_point_v<T_Arg>)
33 return sycl::fabs(arg);
34 else
35 static_assert(!sizeof(T_Arg), "Unsupported data type");
36 }
37 };
38
39 template<std::floating_point T_Arg>
40 struct Sin::Op<SyclMath, T_Arg>
41 {
42 constexpr auto operator()(SyclMath, T_Arg const& arg) const
43 {
44 return sycl::sin(arg);
45 }
46 };
47
48 template<std::floating_point T_Arg>
49 struct Acosh::Op<SyclMath, T_Arg>
50 {
51 constexpr auto operator()(SyclMath, T_Arg const& arg) const
52 {
53 return sycl::acosh(arg);
54 }
55 };
56
57 template<std::floating_point T_Arg>
58 struct Asinh::Op<SyclMath, T_Arg>
59 {
60 constexpr auto operator()(SyclMath, T_Arg const& arg) const
61 {
62 return sycl::asinh(arg);
63 }
64 };
65
66 template<std::floating_point T_Arg>
67 struct Sinh::Op<SyclMath, T_Arg>
68 {
69 constexpr auto operator()(SyclMath, T_Arg const& arg) const
70 {
71 return sycl::sinh(arg);
72 }
73 };
74
75 template<std::floating_point T_Arg>
76 struct Atan::Op<SyclMath, T_Arg>
77 {
78 constexpr auto operator()(SyclMath, T_Arg const& arg) const
79 {
80 return sycl::atan(arg);
81 }
82 };
83
84 template<std::floating_point T_Arg>
85 struct Atanh::Op<SyclMath, T_Arg>
86 {
87 constexpr auto operator()(SyclMath, T_Arg const& arg) const
88 {
89 return sycl::atanh(arg);
90 }
91 };
92
93 template<std::floating_point T_Arg>
94 struct Tanh::Op<SyclMath, T_Arg>
95 {
96 constexpr auto operator()(SyclMath, T_Arg const& arg) const
97 {
98 return sycl::tanh(arg);
99 }
100 };
101
102 template<typename T_Arg>
103 requires(std::is_arithmetic_v<T_Arg>)
104 struct Cbrt::Op<SyclMath, T_Arg>
105 {
106 constexpr auto operator()(SyclMath, T_Arg const& arg) const
107 {
108 if constexpr(std::is_integral_v<T_Arg>)
109 return sycl::cbrt(static_cast<double>(arg)); // Mirror CUDA back-end and use double for ints
110 else if constexpr(std::is_floating_point_v<T_Arg>)
111 return sycl::cbrt(arg);
112 else
113 static_assert(!sizeof(T_Arg), "Unsupported data type");
114 }
115 };
116
117 template<std::floating_point T_Arg>
118 struct Ceil::Op<SyclMath, T_Arg>
119 {
120 constexpr auto operator()(SyclMath, T_Arg const& arg) const
121 {
122 return sycl::ceil(arg);
123 }
124 };
125
126 template<std::floating_point T_Arg>
127 struct Round::Op<SyclMath, T_Arg>
128 {
129 constexpr auto operator()(SyclMath, T_Arg const& arg) const
130 {
131 return sycl::round(arg);
132 }
133 };
134
135 template<std::floating_point T_Arg>
136 struct Lround::Op<SyclMath, T_Arg>
137 {
138 constexpr auto operator()(SyclMath, T_Arg const& arg) const
139 {
140 return static_cast<long>(sycl::round(arg));
141 }
142 };
143
144 template<std::floating_point T_Arg>
145 struct Llround::Op<SyclMath, T_Arg>
146 {
147 constexpr auto operator()(SyclMath, T_Arg const& arg) const
148 {
149 return static_cast<long long>(sycl::round(arg));
150 }
151 };
152
153 template<std::floating_point T_Arg>
154 struct SinCos::Op<SyclMath, T_Arg>
155 {
156 constexpr auto operator()(SyclMath, T_Arg const& arg, T_Arg& result_sin, T_Arg& result_cos) const
157 {
158 result_sin = sycl::sincos(arg, &result_cos);
159 }
160 };
161
162 template<typename T_Arg>
163 requires(std::is_arithmetic_v<T_Arg>)
164 struct Arg::Op<SyclMath, T_Arg>
165 {
166 constexpr auto operator()(SyclMath, T_Arg const& arg) const
167 {
168 if constexpr(std::is_integral_v<T_Arg>)
169 return sycl::atan2(0.0, static_cast<double>(arg));
170 else if constexpr(std::is_floating_point_v<T_Arg>)
171 return sycl::atan2(static_cast<T_Arg>(0.0), arg);
172 else
173 static_assert(!sizeof(T_Arg), "Unsupported data type");
174 }
175 };
176
177 template<std::floating_point T_Y, std::floating_point T_X>
178 struct Atan2::Op<SyclMath, T_Y, T_X>
179 {
180 using CommonT_Bpe = std::common_type_t<T_Y, T_X>;
181
182 auto operator()(SyclMath, T_Y const& y, T_X const& x) const
183 {
184 return sycl::atan2(static_cast<CommonT_Bpe>(y), static_cast<CommonT_Bpe>(x));
185 }
186 };
187
188 template<std::floating_point T_Arg>
189 struct Exp::Op<SyclMath, T_Arg>
190 {
191 constexpr auto operator()(SyclMath, T_Arg const& arg) const
192 {
193 return sycl::exp(arg);
194 }
195 };
196
197 template<std::floating_point T_Arg>
198 struct Sqrt::Op<SyclMath, T_Arg>
199 {
200 constexpr auto operator()(SyclMath, T_Arg const& arg) const
201 {
202 return sycl::sqrt(arg);
203 }
204 };
205
206 template<typename T_Arg>
207 requires(std::is_arithmetic_v<T_Arg>)
208 struct Rsqrt::Op<SyclMath, T_Arg>
209 {
210 constexpr auto operator()(SyclMath, T_Arg const& arg) const
211 {
212 if constexpr(std::is_floating_point_v<T_Arg>)
213 return sycl::rsqrt(arg);
214 else if constexpr(std::is_integral_v<T_Arg>)
215 {
216 // mirror CUDA back-end and use double for ints
217 return sycl::rsqrt(static_cast<double>(arg));
218 }
219 else
220 static_assert(!sizeof(T_Arg), "Unsupported data type");
221 }
222 };
223
224 template<std::floating_point T_Arg>
225 struct Trunc::Op<SyclMath, T_Arg>
226 {
227 constexpr auto operator()(SyclMath, T_Arg const& arg) const
228 {
229 return sycl::trunc(arg);
230 }
231 };
232
233 template<std::floating_point T_Arg>
234 struct Cos::Op<SyclMath, T_Arg>
235 {
236 constexpr auto operator()(SyclMath, T_Arg const& arg) const
237 {
238 return sycl::cos(arg);
239 }
240 };
241
242 template<std::floating_point T_Arg>
243 struct Cosh::Op<SyclMath, T_Arg>
244 {
245 constexpr auto operator()(SyclMath, T_Arg const& arg) const
246 {
247 return sycl::cosh(arg);
248 }
249 };
250
251 template<std::floating_point T_Arg>
252 struct Floor::Op<SyclMath, T_Arg>
253 {
254 constexpr auto operator()(SyclMath, T_Arg const& arg) const
255 {
256 return sycl::floor(arg);
257 }
258 };
259
260 template<std::floating_point T_Arg>
261 struct Erf::Op<SyclMath, T_Arg>
262 {
263 constexpr auto operator()(SyclMath, T_Arg const& arg) const
264 {
265 return sycl::erf(arg);
266 }
267 };
268
269 template<std::floating_point T_Arg>
270 struct Log::Op<SyclMath, T_Arg>
271 {
272 constexpr auto operator()(SyclMath, T_Arg const& arg) const
273 {
274 return sycl::log(arg);
275 }
276 };
277
278 template<std::floating_point T_Arg>
279 struct Log2::Op<SyclMath, T_Arg>
280 {
281 constexpr auto operator()(SyclMath, T_Arg const& arg) const
282 {
283 return sycl::log2(arg);
284 }
285 };
286
287 template<std::floating_point T_Arg>
288 struct Log10::Op<SyclMath, T_Arg>
289 {
290 constexpr auto operator()(SyclMath, T_Arg const& arg) const
291 {
292 return sycl::log10(arg);
293 }
294 };
295
296 template<std::floating_point T_Arg>
297 struct Tan::Op<SyclMath, T_Arg>
298 {
299 constexpr auto operator()(SyclMath, T_Arg const& arg) const
300 {
301 return sycl::tan(arg);
302 }
303 };
304
305 template<std::floating_point T_Arg>
306 struct Asin::Op<SyclMath, T_Arg>
307 {
308 constexpr auto operator()(SyclMath, T_Arg const& arg) const
309 {
310 return sycl::asin(arg);
311 }
312 };
313
314 template<std::floating_point T_Arg>
315 struct Acos::Op<SyclMath, T_Arg>
316 {
317 constexpr auto operator()(SyclMath, T_Arg const& arg) const
318 {
319 return sycl::acos(arg);
320 }
321 };
322
323 // Route SYCL predicates through shared helper to match host/CUDA semantics exactly.
324 template<std::floating_point T_Arg>
325 struct Isnan::Op<SyclMath, T_Arg>
326 {
327 constexpr auto operator()(SyclMath, T_Arg const& arg) const
328 {
329 return ieeeIsnan(arg);
330 }
331 };
332
333 template<std::floating_point T_Arg>
334 struct Isinf::Op<SyclMath, T_Arg>
335 {
336 constexpr auto operator()(SyclMath, T_Arg const& arg) const
337 {
338 return ieeeIsinf(arg);
339 }
340 };
341
342 template<std::floating_point T_Arg>
343 struct Isfinite::Op<SyclMath, T_Arg>
344 {
345 constexpr auto operator()(SyclMath, T_Arg const& arg) const
346 {
347 return ieeeIsfinite(arg);
348 }
349 };
350
351 template<std::floating_point T_Arg>
352 struct Conj::Op<SyclMath, T_Arg>
353 {
354 constexpr auto operator()(SyclMath, T_Arg const& arg) const
355 {
356 return Complex<T_Arg>{arg, T_Arg{0.0}};
357 }
358 };
359
360 template<std::floating_point TMag, std::floating_point TSgn>
361 struct Copysign::Op<SyclMath, TMag, TSgn>
362 {
363 using TCommon = std::common_type_t<TMag, TSgn>;
364
365 constexpr auto operator()(SyclMath, TMag const& mag, TSgn const& sgn) const
366 {
367 return sycl::copysign(static_cast<TCommon>(mag), static_cast<TCommon>(sgn));
368 }
369 };
370
371 template<typename T_A, typename T_B>
372 requires(std::is_arithmetic_v<T_A> && std::is_arithmetic_v<T_B>)
373 struct Min::Op<SyclMath, T_A, T_B>
374 {
375 constexpr auto operator()(SyclMath, T_A const& a, T_B const& b) const
376 {
377 if constexpr(std::is_integral_v<T_A> && std::is_integral_v<T_B>)
378 return sycl::min(a, b);
379 else if constexpr(std::is_floating_point_v<T_A> || std::is_floating_point_v<T_B>)
380 return sycl::fmin(a, b);
381 else if constexpr(
382 (std::is_floating_point_v<T_A> && std::is_integral_v<T_B>)
383 || (std::is_integral_v<T_A> && std::is_floating_point_v<T_B>) )
384 return sycl::fmin(static_cast<double>(a), static_cast<double>(b)); // mirror CUDA back-end
385 else
386 static_assert(!sizeof(T_A), "Unsupported data types");
387 }
388 };
389
390 template<typename T_A, typename T_B>
391 requires(std::is_arithmetic_v<T_A> && std::is_arithmetic_v<T_B>)
392 struct Max::Op<SyclMath, T_A, T_B>
393 {
394 constexpr auto operator()(SyclMath, T_A const& a, T_B const& b) const
395 {
396 if constexpr(std::is_integral_v<T_A> && std::is_integral_v<T_B>)
397 return sycl::max(a, b);
398 else if constexpr(std::is_floating_point_v<T_A> || std::is_floating_point_v<T_B>)
399 return sycl::fmax(a, b);
400 else if constexpr(
401 (std::is_floating_point_v<T_A> && std::is_integral_v<T_B>)
402 || (std::is_integral_v<T_A> && std::is_floating_point_v<T_B>) )
403 return sycl::fmax(static_cast<double>(a), static_cast<double>(b)); // mirror CUDA back-end
404 else
405 static_assert(!sizeof(T_A), "Unsupported data types");
406 }
407 };
408
409 template<std::floating_point T_Base, std::floating_point T_Exp>
410 struct Pow::Op<SyclMath, T_Base, T_Exp>
411 {
412 using TCommon = std::common_type_t<T_Base, T_Exp>;
413
414 constexpr auto operator()(SyclMath, T_Base const& base, T_Exp const& exp) const
415 {
416 return sycl::pow(static_cast<TCommon>(base), static_cast<TCommon>(exp));
417 }
418 };
419
420 template<std::floating_point T_X, std::floating_point T_Y>
421 struct Fmod::Op<SyclMath, T_X, T_Y>
422 {
423 using TCommon = std::common_type_t<T_X, T_Y>;
424
425 constexpr auto operator()(SyclMath, T_X const& x, T_Y const& y) const
426 {
427 return sycl::fmod(static_cast<TCommon>(x), static_cast<TCommon>(y));
428 }
429 };
430
431 template<std::floating_point T_X, std::floating_point T_Y>
432 struct Remainder::Op<SyclMath, T_X, T_Y>
433 {
434 using TCommon = std::common_type_t<T_X, T_Y>;
435
436 constexpr auto operator()(SyclMath, T_X const& x, T_Y const& y) const
437 {
438 return sycl::remainder(static_cast<TCommon>(x), static_cast<TCommon>(y));
439 }
440 };
441
442 template<std::floating_point T_X, std::floating_point T_Y, std::floating_point T_Z>
443 struct Fma::Op<SyclMath, T_X, T_Y, T_Z>
444 {
445 constexpr auto operator()(SyclMath, T_X const& x, T_Y const& y, T_Z const& z) const
446 {
447 return sycl::fma(x, y, z);
448 }
449 };
450
451} // namespace alpaka::math::internal
452
453#endif
constexpr auto arg(auto const &arg)
Definition math.hpp:146