15#ifndef GPUCOMMONMATH_H
16#define GPUCOMMONMATH_H
20#if defined(__CUDACC__) && !defined(__clang__) && !defined(GPUCA_GPUCODE_COMPILEKERNELS) && !defined(GPUCA_GPUCODE_HOSTONLY)
21#include <sm_20_atomic_functions.h>
24#if !defined(GPUCA_GPUCODE_DEVICE)
32#if !defined(GPUCA_GPUCODE_COMPILEKERNELS) && (!defined(GPUCA_GPUCODE_DEVICE) || defined(__CUDACC__) || defined(__HIPCC__))
37#if defined(GPUCA_GPUCODE_DEVICE) && (defined(__CUDACC__) || defined(__HIPCC__))
38 #define GPUCA_CHOICE(c1, c2, c3) (c2)
39#elif defined(GPUCA_GPUCODE_DEVICE) && (defined(__OPENCL__) || defined(__METAL__))
40 #define GPUCA_CHOICE(c1, c2, c3) (c3)
42 #define GPUCA_CHOICE(c1, c2, c3) (c1)
54 GPUhd() constexpr static T Min(const T
x, const T
y)
59 GPUhd() constexpr static T Max(const T
x, const T
y)
63 template <
class T,
class S,
class R>
65 template <class T, class
S, class
R>
67 template <class T, class
S, class
R>
70 GPUdi() constexpr static T Clamp(const T
v, const T
lo, const T
hi)
72 return Max(
lo, Min(
v,
hi));
75 GPUd() constexpr static
double Sqrtd(
double x);
76 GPUd() static
float InvSqrt(
float x);
78 GPUdi() constexpr static T Square(T
x)
84 GPUd() constexpr static
float ASin(
float x);
85 GPUd() constexpr static
double ASind(
double x);
86 GPUd() constexpr static
float ACos(
float x);
87 GPUd() constexpr static
double ACosd(
double x);
88 GPUd() constexpr static
float ATan(
float x);
89 GPUd() constexpr static
double ATand(
double x);
90 GPUhd() constexpr static
float ATan2(
float y,
float x);
91 GPUd() constexpr static
double ATan2d(
double y,
double x);
93 GPUd() constexpr static
double Sind(
double x);
95 GPUd() constexpr static
double Cosd(
double x);
96 GPUhdni() static
void SinCos(
float x,
float&
s,
float&
c);
97 GPUhdni() static
void SinCosd(
double x,
double&
s,
double&
c);
99 GPUd() constexpr static
double Tand(
double x);
100 GPUd() constexpr static
float Pow(
float x,
float y);
102 GPUd() constexpr static
double Logd(
double x);
104 GPUd() constexpr static
double Expd(
double x);
106 GPUd() constexpr static
double Copysignd(
double x,
double y);
107 GPUd() constexpr static
float TwoPi() {
return 6.2831853f; }
108 GPUd() constexpr static
float Pi() {
return 3.1415927f; }
111 GPUd() static uint32_t Float2UIntReint(const
float&
x);
112 GPUd() constexpr static uint32_t Float2UIntRn(
float x) {
return (uint32_t)(int32_t)(
x + 0.5f); }
113 GPUd() constexpr static int32_t Float2IntRn(
float x);
114 GPUd() constexpr static
float Modf(
float x,
float y);
115 GPUhdi() static
float Remainderf(
float x,
float y);
116 GPUd() constexpr static
bool Finite(
float x);
117 GPUd() constexpr static
bool IsNaN(
float x);
119 GPUd() constexpr static
float QuietNaN() {
return GPUCA_CHOICE(std::numeric_limits<float>::quiet_NaN(), __builtin_nanf(
""), NAN); }
121 GPUd() constexpr static uint32_t Clz(uint32_t
val);
122 GPUd() constexpr static uint32_t Ctz(uint32_t
val);
123 GPUd() constexpr static uint32_t Popcount(uint32_t
val);
124 GPUd() constexpr static uint32_t Clz64(uint64_t
val);
125 GPUd() constexpr static uint32_t Ctz64(uint64_t
val);
126 GPUd() constexpr static uint32_t Popcount64(uint64_t
val);
132 GPUhdi() constexpr static
float Hypot(
float x,
float y,
float z,
float w) {
return Sqrt(
x *
x +
y *
y +
z *
z +
w *
w); }
134 template <
typename T>
135 GPUhd() constexpr static
void Swap(T&
a, T&
b);
140 return GPUCommonMath::AtomicExchInternal(addr,
val);
146 return GPUCommonMath::AtomicCASInternal(addr,
cmp,
val);
152 return GPUCommonMath::AtomicAddInternal(addr,
val);
157 GPUCommonMath::AtomicMaxInternal(addr,
val);
162 GPUCommonMath::AtomicMinInternal(addr,
val);
167 return GPUCommonMath::AtomicLoadInternal<T>(addr);
172 GPUCommonMath::AtomicStoreInternal(addr,
val);
177 return GPUCommonMath::AtomicExchInternal(addr,
val);
182 return GPUCommonMath::AtomicAddInternal(addr,
val);
187 GPUCommonMath::AtomicMaxInternal(addr,
val);
192 GPUCommonMath::AtomicMinInternal(addr,
val);
194 GPUd() constexpr static int32_t Mul24(int32_t
a, int32_t
b);
195 GPUd() constexpr static
float FMulRZ(
float a,
float b);
197 template <int32_t I, class T>
198 GPUd() constexpr static T nextMultipleOf(T
val);
200 template <typename... Args>
204 template <class
S, class T>
205 GPUd() static uint32_t AtomicExchInternal(
S* addr, T
val);
206 template <class
S, class T>
207 GPUd() static
bool AtomicCASInternal(
S* addr, T
cmp, T
val);
208 template <class
S, class T>
209 GPUd() static uint32_t AtomicAddInternal(
S* addr, T
val);
210 template <class
S, class T>
211 GPUd() static
void AtomicMaxInternal(
S* addr, T
val);
212 template <class
S, class T>
213 GPUd() static
void AtomicMinInternal(
S* addr, T
val);
214 template <class T, class
S>
215 GPUd() static T AtomicLoadInternal(
S* addr);
216 template <class
S, class T>
217 GPUd() static
void AtomicStoreInternal(
S* addr, T
val);
222template <typename... Args>
225 if constexpr (
sizeof...(Args) == 0) {
228 return w *
w + Sum2(
args...);
235#ifndef GPUCA_GPUCODE_DEVICE
237#elif defined(__CUDACC__) || defined(__HIPCC__)
239#elif defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
242 char* d = (
char*)
dst;
243 const char*
s = (
const char*)
src;
244 for (
size_t i = 0;
i <
size;
i++) {
250template <
int32_t I,
class T>
251GPUdi() constexpr T GPUCommonMath::nextMultipleOf(T
val)
253 if constexpr (I & (I - 1)) {
260 return (
val + I - 1) & ~(
T)(I - 1);
267#if !defined(GPUCA_GPUCODE) || defined(__OPENCL__) || defined(__OPENCL_HOST__) || defined(__METAL__) || defined(__METAL_HOST__) || defined(__CPUDEVICE__)
271 return make_float2(
x,
y);
275GPUdi() constexpr
float GPUCommonMath::Modf(
float x,
float y) {
return GPUCA_CHOICE(fmodf(
x,
y), fmodf(
x,
y), fmod(
x,
y)); }
279 const float r = fmod(
x,
y),
h = 0.5f * fabs(
y),
a = fabs(
r);
281 return r - copysign(
y,
r);
283 if (
a ==
h && fmod((
x -
r) /
y, 2.f) != 0.f) {
284 return r - copysign(
y,
r);
292GPUdi() uint32_t GPUCommonMath::Float2UIntReint(const
float&
x)
294#if defined(GPUCA_GPUCODE_DEVICE) && (defined(__CUDACC__) || defined(__HIPCC__))
295 return __float_as_uint(
x);
296#elif defined(GPUCA_GPUCODE_DEVICE) && defined(__OPENCL__)
298#elif !defined(GPUCA_GPUCODE_DEVICE)
299 return __builtin_bit_cast(uint32_t,
x);
301 return reinterpret_cast<const uint32_t&
>(
x);
306GPUdi()
constexpr float GPUCommonMath::Round(
float x) {
return GPUCA_CHOICE(roundf(
x), roundf(
x), round(
x)); }
307GPUdi() constexpr int32_t GPUCommonMath::Float2IntRn(
float x) {
return (int32_t)
Round(
x); }
309GPUdi() constexpr
float GPUCommonMath::ATan(
float x) {
return GPUCA_CHOICE((
float)atan((
double)
x), (
float)atan((
double)
x), atan(
x)); }
310GPUhdi() constexpr
float GPUCommonMath::ATan2(
float y,
float x) {
return GPUCA_CHOICE((
float)atan2((
double)
y, (
double)
x), (
float)atan2((
double)
y, (
double)
x), atan2(
y,
x)); }
311GPUdi() constexpr
float GPUCommonMath::
Sin(
float x) {
return GPUCA_CHOICE((
float)sin((
double)
x), (
float)sin((
double)
x), sin(
x)); }
312GPUdi() constexpr
float GPUCommonMath::
Cos(
float x) {
return GPUCA_CHOICE((
float)cos((
double)
x), (
float)cos((
double)
x), cos(
x)); }
313GPUdi() constexpr
float GPUCommonMath::
Tan(
float x) {
return GPUCA_CHOICE((
float)tanf((
double)
x), (
float)tanf((
double)
x), tan(
x)); }
314GPUdi() constexpr
float GPUCommonMath::Pow(
float x,
float y) {
return GPUCA_CHOICE((
float)pow((
double)
x, (
double)
y), pow((
double)
x, (
double)
y), pow(
x,
y)); }
315GPUdi() constexpr
float GPUCommonMath::ASin(
float x) {
return GPUCA_CHOICE((
float)asin((
double)
x), (
float)asin((
double)
x), asin(
x)); }
316GPUdi() constexpr
float GPUCommonMath::ACos(
float x) {
return GPUCA_CHOICE((
float)acos((
double)
x), (
float)acos((
double)
x), acos(
x)); }
317GPUdi() constexpr
float GPUCommonMath::
Log(
float x) {
return GPUCA_CHOICE((
float)log((
double)
x), (
float)log((
double)
x), log(
x)); }
319GPUdi() constexpr
bool GPUCommonMath::Finite(
float x) {
return GPUCA_CHOICE(std::isfinite(
x), isfinite(
x), isfinite(
x)); }
325GPUdi() constexpr
float GPUCommonMath::ATan(
float x) {
return GPUCA_CHOICE(atanf(
x), atanf(
x), atan(
x)); }
326GPUhdi() constexpr
float GPUCommonMath::ATan2(
float y,
float x) {
return GPUCA_CHOICE(atan2f(
y,
x), atan2f(
y,
x), atan2(
y,
x)); }
331GPUdi() constexpr
float GPUCommonMath::ASin(
float x) {
return GPUCA_CHOICE(asinf(
x), asinf(
x), asin(
x)); }
332GPUdi() constexpr
float GPUCommonMath::ACos(
float x) {
return GPUCA_CHOICE(acosf(
x), acosf(
x), acos(
x)); }
335GPUdi() constexpr
bool GPUCommonMath::Finite(
float x) {
return true; }
336GPUdi() constexpr
bool GPUCommonMath::IsNaN(
float x) {
return false; }
339GPUhdi()
void GPUCommonMath::SinCos(
float x,
float&
s,
float&
c)
345#if !defined(GPUCA_GPUCODE_DEVICE) && defined(__APPLE__)
346 __sincosf(
x, &
s, &
c);
347#elif !defined(GPUCA_GPUCODE_DEVICE) && (defined(__GNU_SOURCE__) || defined(_GNU_SOURCE) || defined(GPUCA_GPUCODE))
349#elif defined(__METAL__)
352 s = sincos(
x, metalCos);
361GPUhdi()
void GPUCommonMath::SinCosd(
double x,
double&
s,
double&
c)
363#if !defined(GPUCA_GPUCODE_DEVICE) && defined(__APPLE__)
365#elif !defined(GPUCA_GPUCODE_DEVICE) && (defined(__GNU_SOURCE__) || defined(_GNU_SOURCE) || defined(GPUCA_GPUCODE))
372GPUdi() constexpr
double GPUCommonMath::Sqrtd(
double x) {
return GPUCA_CHOICE(std::sqrt(
x), sqrt(
x), sqrt(
x)); }
373GPUdi() constexpr
double GPUCommonMath::ASind(
double x) {
return GPUCA_CHOICE(std::asin(
x), asin(
x), asin(
x)); }
374GPUdi() constexpr
double GPUCommonMath::ACosd(
double x) {
return GPUCA_CHOICE(std::acos(
x), acos(
x), acos(
x)); }
375GPUdi() constexpr
double GPUCommonMath::ATand(
double x) {
return GPUCA_CHOICE(std::atan(
x), atan(
x), atan(
x)); }
376GPUdi() constexpr
double GPUCommonMath::ATan2d(
double y,
double x) {
return GPUCA_CHOICE(std::atan2(
y,
x), atan2(
y,
x), atan2(
y,
x)); }
377GPUdi() constexpr
double GPUCommonMath::Sind(
double x) {
return GPUCA_CHOICE(std::sin(
x), sin(
x), sin(
x)); }
378GPUdi() constexpr
double GPUCommonMath::Cosd(
double x) {
return GPUCA_CHOICE(std::cos(
x), cos(
x), cos(
x)); }
379GPUdi() constexpr
double GPUCommonMath::Tand(
double x) {
return GPUCA_CHOICE(std::tan(
x), tan(
x), tan(
x)); }
380GPUdi() constexpr
double GPUCommonMath::Logd(
double x) {
return GPUCA_CHOICE(std::log(
x), log(
x), log(
x)); }
382GPUdi() constexpr
double GPUCommonMath::Copysignd(
double x,
double y) {
return GPUCA_CHOICE(std::copysign(
x,
y), copysign(
x,
y), copysign(
x,
y)); }
385GPUdi() constexpr uint32_t GPUCommonMath::Clz(uint32_t
x)
387#if (defined(__GNUC__) || defined(__clang__) || defined(__CUDACC__) || defined(__HIPCC__))
388 return x == 0 ? 32 :
GPUCA_CHOICE(__builtin_clz(
x), __clz(
x), __builtin_clz(
x));
390 for (int32_t
i = 31;
i >= 0;
i--) {
399GPUdi() constexpr uint32_t GPUCommonMath::Ctz(uint32_t
x)
401#if (defined(__GNUC__) || defined(__clang__) || defined(__CUDACC__) || defined(__HIPCC__))
402 return x == 0 ? 32 :
GPUCA_CHOICE(__builtin_ctz(
x), __ffs(
x) - 1, __builtin_ctz(
x));
404 for (uint32_t
i = 0;
i < 32; ++
i) {
413GPUdi() constexpr uint32_t GPUCommonMath::Popcount(uint32_t
x)
415#if (defined(__GNUC__) || defined(__clang__) || defined(__CUDACC__) || defined(__HIPCC__)) && !defined(__OPENCL__)
417 return GPUCA_CHOICE(__builtin_popcount(
x), __popc(
x), __builtin_popcount(
x));
419 x =
x - ((
x >> 1) & 0x55555555);
420 x = (
x & 0x33333333) + ((
x >> 2) & 0x33333333);
421 return (((
x + (
x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
425GPUdi() constexpr uint32_t GPUCommonMath::Clz64(uint64_t
x)
427#if (defined(__GNUC__) || defined(__clang__) || defined(__CUDACC__) || defined(__HIPCC__))
428 return x == 0 ? 64 :
GPUCA_CHOICE(__builtin_clzll(
x), __clzll(
x), __builtin_clzll(
x));
430 for (int32_t
i = 63;
i >= 0;
i--) {
431 if (
x & (1ull <<
i)) {
439GPUdi() constexpr uint32_t GPUCommonMath::Ctz64(uint64_t
x)
441#if (defined(__GNUC__) || defined(__clang__) || defined(__CUDACC__) || defined(__HIPCC__))
442 return x == 0 ? 64 :
GPUCA_CHOICE(__builtin_ctzll(
x), __ffsll((
long long)
x) - 1, __builtin_ctzll(
x));
444 for (uint32_t
i = 0;
i < 64; ++
i) {
445 if (
x & (1ull <<
i)) {
453GPUdi() constexpr uint32_t GPUCommonMath::Popcount64(uint64_t
x)
455#if (defined(__GNUC__) || defined(__clang__) || defined(__CUDACC__) || defined(__HIPCC__)) && !defined(__OPENCL__)
457 return GPUCA_CHOICE(__builtin_popcountll(
x), __popcll(
x), __builtin_popcountll(
x));
459 return Popcount((uint32_t)
x) + Popcount((uint32_t)(
x >> 32));
464GPUhdi() constexpr
void GPUCommonMath::Swap(T&
a, T&
b)
466#ifndef GPUCA_GPUCODE_DEVICE
475template <
class T,
class S,
class R>
486template <
class T,
class S,
class R>
497template <
class T,
class S,
class R>
518GPUdi() float GPUCommonMath::InvSqrt(
float _x)
521 return 1.f /
Sqrt(_x);
523#if defined(__CUDACC__) || defined(__HIPCC__)
524 return __frsqrt_rn(_x);
525#elif (defined(__OPENCL__) || defined(__METAL__)) && defined(__clang__)
526 return 1.f / sqrt(_x);
527#elif !defined(__OPENCL__) && (defined(__FAST_MATH__) || defined(__clang__))
528 return 1.f / sqrtf(_x);
534 const float xhalf = 0.5f *
x.f;
535 x.i = 0x5f3759df - (
x.i >> 1);
536 x.f =
x.f * (1.5f - xhalf *
x.f *
x.f);
550GPUhdi() constexpr
double GPUCommonMath::
Abs<
double>(
double x)
556static_assert(GPUCommonMath::Abs<double>(GPUdoubleBinary64::fromBits(0xBFF0000000000001ULL)).bits() == 0x3FF0000000000001ULL,
557 "Abs on the emulated double must clear the sign bit and keep every other one");
580GPUdi() threadgroup metal::atomic<T>* GPUCommonMathMetalAtomic(threadgroup T* p)
582 return reinterpret_cast<threadgroup metal::atomic<T>*
>(p);
585GPUdi() device metal::atomic<T>* GPUCommonMathMetalAtomic(T* p)
587 return (device metal::atomic<T>*)p;
591template <
class S,
class T>
592GPUdi() uint32_t GPUCommonMath::AtomicExchInternal(
S* addr, T
val)
594#if defined(GPUCA_GPUCODE) && defined(__OPENCL__) && (!defined(__clang__) || defined(GPUCA_OPENCL_CLANG_C11_ATOMICS))
595 return ::atomic_exchange(addr,
val);
596#elif defined(GPUCA_GPUCODE) && defined(__OPENCL__)
597 return ::atomic_xchg(addr,
val);
598#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
599 return ::atomicExch(addr,
val);
600#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
601 return atomic_exchange_explicit(GPUCommonMathMetalAtomic(addr),
val, memory_order_relaxed);
602#elif defined(WITH_OPENMP)
604 __atomic_exchange(addr, &
val, &old, __ATOMIC_SEQ_CST);
607 return reinterpret_cast<std::atomic<T>*
>(addr)->exchange(
val);
611template <
class S,
class T>
612GPUdi() bool GPUCommonMath::AtomicCASInternal(
S* addr, T
cmp, T
val)
614#if defined(GPUCA_GPUCODE) && defined(__OPENCL__) && (!defined(__clang__) || defined(GPUCA_OPENCL_CLANG_C11_ATOMICS))
615 return ::atomic_compare_exchange(addr,
cmp,
val) ==
cmp;
616#elif defined(GPUCA_GPUCODE) && defined(__OPENCL__)
617 return ::atomic_cmpxchg(addr,
cmp,
val) ==
cmp;
618#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
619 return ::atomicCAS(addr,
cmp,
val) ==
cmp;
620#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
621 return atomic_compare_exchange_weak_explicit(GPUCommonMathMetalAtomic(addr), &
cmp,
val, memory_order_relaxed, memory_order_relaxed);
622#elif defined(WITH_OPENMP)
623 return __atomic_compare_exchange(addr, &
cmp, &
val,
true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
625 return reinterpret_cast<std::atomic<T>*
>(addr)->compare_exchange_strong(
cmp,
val);
629template <
class S,
class T>
630GPUdi() uint32_t GPUCommonMath::AtomicAddInternal(
S* addr, T
val)
632#if defined(GPUCA_GPUCODE) && defined(__OPENCL__) && (!defined(__clang__) || defined(GPUCA_OPENCL_CLANG_C11_ATOMICS))
633 return ::atomic_fetch_add(addr,
val);
634#elif defined(GPUCA_GPUCODE) && defined(__OPENCL__)
635 return ::atomic_add(addr,
val);
636#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
637 return ::atomicAdd(addr,
val);
638#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
639 return atomic_fetch_add_explicit(GPUCommonMathMetalAtomic(addr),
val, memory_order_relaxed);
640#elif defined(WITH_OPENMP)
641 return __atomic_add_fetch(addr,
val, __ATOMIC_SEQ_CST) -
val;
643 return reinterpret_cast<std::atomic<T>*
>(addr)->fetch_add(
val);
647template <
class S,
class T>
650#if defined(GPUCA_GPUCODE) && defined(__OPENCL__) && (!defined(__clang__) || defined(GPUCA_OPENCL_CLANG_C11_ATOMICS))
651 ::atomic_fetch_max(addr,
val);
652#elif defined(GPUCA_GPUCODE) && defined(__OPENCL__)
653 ::atomic_max(addr,
val);
654#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
655 ::atomicMax(addr,
val);
656#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
657 atomic_fetch_max_explicit(GPUCommonMathMetalAtomic(addr),
val, memory_order_relaxed);
660 while ((current = *(
volatile S*)addr) <
val && !AtomicCASInternal(addr, current,
val)) {
665template <
class S,
class T>
668#if defined(GPUCA_GPUCODE) && defined(__OPENCL__) && (!defined(__clang__) || defined(GPUCA_OPENCL_CLANG_C11_ATOMICS))
669 ::atomic_fetch_min(addr,
val);
670#elif defined(GPUCA_GPUCODE) && defined(__OPENCL__)
671 ::atomic_min(addr,
val);
672#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
673 ::atomicMin(addr,
val);
674#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
675 atomic_fetch_min_explicit(GPUCommonMathMetalAtomic(addr),
val, memory_order_relaxed);
678 while ((current = *(
volatile S*)addr) >
val && !AtomicCASInternal(addr, current,
val)) {
684template <
class T,
class S>
685GPUdi() T GPUCommonMath::AtomicLoadInternal(
S* addr)
687#if defined(GPUCA_GPUCODE) && defined(__OPENCL__) && (!defined(__clang__) || defined(GPUCA_OPENCL_CLANG_C11_ATOMICS))
688 return ::atomic_load_explicit(addr, memory_order_relaxed);
689#elif defined(GPUCA_GPUCODE) && (defined(__OPENCL__) || defined(__CUDACC__) || defined(__HIPCC__))
690 return *(
volatile S*)addr;
691#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
692 return atomic_load_explicit(GPUCommonMathMetalAtomic(addr), memory_order_relaxed);
693#elif defined(WITH_OPENMP)
695 __atomic_load(addr, &ret, __ATOMIC_RELAXED);
698 return reinterpret_cast<std::atomic<T>*
>(addr)->load(std::memory_order_relaxed);
702template <
class S,
class T>
703GPUdi()
void GPUCommonMath::AtomicStoreInternal(
S* addr, T
val)
705#if defined(GPUCA_GPUCODE) && defined(__OPENCL__) && (!defined(__clang__) || defined(GPUCA_OPENCL_CLANG_C11_ATOMICS))
706 ::atomic_store_explicit(addr,
val, memory_order_relaxed);
707#elif defined(GPUCA_GPUCODE) && (defined(__OPENCL__) || defined(__CUDACC__) || defined(__HIPCC__))
708 *(
volatile S*)addr =
val;
709#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
710 atomic_store_explicit(GPUCommonMathMetalAtomic(addr),
val, memory_order_relaxed);
711#elif defined(WITH_OPENMP)
712 __atomic_store(addr, &
val, __ATOMIC_RELAXED);
714 reinterpret_cast<std::atomic<T>*
>(addr)->store(
val, std::memory_order_relaxed);
718#if (defined(__CUDACC__) || defined(__HIPCC__)) && !defined(G__ROOT) && !defined(__CLING__)
719#define GPUCA_HAVE_ATOMIC_MINMAX_FLOAT
727 AtomicMaxInternal((
GPUAtomic(int32_t)*)addr, __float_as_int(
val));
729 AtomicMinInternal((
GPUAtomic(uint32_t)*)addr, __float_as_uint(
val));
739 AtomicMinInternal((
GPUAtomic(int32_t)*)addr, __float_as_int(
val));
741 AtomicMaxInternal((
GPUAtomic(uint32_t)*)addr, __float_as_uint(
val));
uint64_t exp(uint64_t base, uint8_t exp) noexcept
#define GPUCA_DETERMINISTIC_CODE(det, indet)
#define GPUCA_CHOICE(c1, c2, c3)
Class for time synchronization of RawReader instances.
GPUd() const expr static float Pi()
GPUdi() static void AtomicStore(GPUglobalref() GPUgeneric() GPUAtomic(T) *addr
GPUhd() const expr static T Min(const T x
GPUd() const expr static float QuietNaN()
GPUdi() static void AtomicMax(GPUglobalref() GPUgeneric() GPUAtomic(T) *addr
GPUd() const expr static int32_t Float2IntRn(float x)
GPUd() const expr static float Round(float x)
GPUhdni() const expr static float Sqrt(float x)
GPUdi() static void AtomicMin(GPUglobalref() GPUgeneric() GPUAtomic(T) *addr
GPUdi() const expr static T Clamp(const T v
GPUd() static float2 MakeFloat2(float x
GPUhd() const expr static T Max(const T x
GPUdi() static T AtomicAddShared(GPUsharedref() GPUgeneric() GPUAtomic(T) *addr
GPUhd() const expr static T Abs(T x)
GPUdi() static T AtomicAdd(GPUglobalref() GPUgeneric() GPUAtomic(T) *addr
GPUdi() static T AtomicExchShared(GPUsharedref() GPUgeneric() GPUAtomic(T) *addr
GPUd() static uint32_t Float2UIntReint(const float &x)
GPUd() static T MinWithRef(T x
GPUdi() static void AtomicMinShared(GPUsharedref() GPUgeneric() GPUAtomic(T) *addr
GPUhdi() static float Remainderf(float x
GPUdi() static T AtomicLoad(GPUglobalref() GPUgeneric() GPUAtomic(T) *addr)
GPUhdi() const expr static float Hypot(float x
GPUd() const expr static double Copysignd(double x
GPUd() const expr static uint32_t Clz(uint32_t val)
GPUdi() static void AtomicMaxShared(GPUsharedref() GPUgeneric() GPUAtomic(T) *addr
GLboolean GLboolean GLboolean b
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLboolean GLboolean GLboolean GLboolean a
GLubyte GLubyte GLubyte GLubyte w
GLdouble GLdouble GLdouble z