clang 20.0.0git
__clang_cuda_complex_builtins.h
Go to the documentation of this file.
1/*===-- __clang_cuda_complex_builtins - CUDA impls of runtime complex fns ---===
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
10#ifndef __CLANG_CUDA_COMPLEX_BUILTINS
11#define __CLANG_CUDA_COMPLEX_BUILTINS
12
13// This header defines __muldc3, __mulsc3, __divdc3, and __divsc3. These are
14// libgcc functions that clang assumes are available when compiling c99 complex
15// operations. (These implementations come from libc++, and have been modified
16// to work with CUDA and OpenMP target offloading [in C and C++ mode].)
17
18#pragma push_macro("__DEVICE__")
19#if defined(__OPENMP_NVPTX__) || defined(__OPENMP_AMDGCN__)
20#pragma omp declare target
21#define __DEVICE__ __attribute__((noinline, nothrow, cold, weak))
22#else
23#define __DEVICE__ __device__ inline
24#endif
25
26// To make the algorithms available for C and C++ in CUDA and OpenMP we select
27// different but equivalent function versions. TODO: For OpenMP we currently
28// select the native builtins as the overload support for templates is lacking.
29#if !defined(__OPENMP_NVPTX__) && !defined(__OPENMP_AMDGCN__)
30#define _ISNANd std::isnan
31#define _ISNANf std::isnan
32#define _ISINFd std::isinf
33#define _ISINFf std::isinf
34#define _ISFINITEd std::isfinite
35#define _ISFINITEf std::isfinite
36#define _COPYSIGNd std::copysign
37#define _COPYSIGNf std::copysign
38#define _SCALBNd std::scalbn
39#define _SCALBNf std::scalbn
40#define _ABSd std::abs
41#define _ABSf std::abs
42#define _LOGBd std::logb
43#define _LOGBf std::logb
44// Rather than pulling in std::max from algorithm everytime, use available ::max.
45#define _fmaxd max
46#define _fmaxf max
47#else
48#ifdef __AMDGCN__
49#define _ISNANd __ocml_isnan_f64
50#define _ISNANf __ocml_isnan_f32
51#define _ISINFd __ocml_isinf_f64
52#define _ISINFf __ocml_isinf_f32
53#define _ISFINITEd __ocml_isfinite_f64
54#define _ISFINITEf __ocml_isfinite_f32
55#define _COPYSIGNd __ocml_copysign_f64
56#define _COPYSIGNf __ocml_copysign_f32
57#define _SCALBNd __ocml_scalbn_f64
58#define _SCALBNf __ocml_scalbn_f32
59#define _ABSd __ocml_fabs_f64
60#define _ABSf __ocml_fabs_f32
61#define _LOGBd __ocml_logb_f64
62#define _LOGBf __ocml_logb_f32
63#define _fmaxd __ocml_fmax_f64
64#define _fmaxf __ocml_fmax_f32
65#else
66#define _ISNANd __nv_isnand
67#define _ISNANf __nv_isnanf
68#define _ISINFd __nv_isinfd
69#define _ISINFf __nv_isinff
70#define _ISFINITEd __nv_isfinited
71#define _ISFINITEf __nv_finitef
72#define _COPYSIGNd __nv_copysign
73#define _COPYSIGNf __nv_copysignf
74#define _SCALBNd __nv_scalbn
75#define _SCALBNf __nv_scalbnf
76#define _ABSd __nv_fabs
77#define _ABSf __nv_fabsf
78#define _LOGBd __nv_logb
79#define _LOGBf __nv_logbf
80#define _fmaxd __nv_fmax
81#define _fmaxf __nv_fmaxf
82#endif
83#endif
84
85#if defined(__cplusplus)
86extern "C" {
87#endif
88
89__DEVICE__ double _Complex __muldc3(double __a, double __b, double __c,
90 double __d) {
91 double __ac = __a * __c;
92 double __bd = __b * __d;
93 double __ad = __a * __d;
94 double __bc = __b * __c;
95 double _Complex z;
96 __real__(z) = __ac - __bd;
97 __imag__(z) = __ad + __bc;
98 if (_ISNANd(__real__(z)) && _ISNANd(__imag__(z))) {
99 int __recalc = 0;
100 if (_ISINFd(__a) || _ISINFd(__b)) {
101 __a = _COPYSIGNd(_ISINFd(__a) ? 1 : 0, __a);
102 __b = _COPYSIGNd(_ISINFd(__b) ? 1 : 0, __b);
103 if (_ISNANd(__c))
104 __c = _COPYSIGNd(0, __c);
105 if (_ISNANd(__d))
106 __d = _COPYSIGNd(0, __d);
107 __recalc = 1;
108 }
109 if (_ISINFd(__c) || _ISINFd(__d)) {
110 __c = _COPYSIGNd(_ISINFd(__c) ? 1 : 0, __c);
111 __d = _COPYSIGNd(_ISINFd(__d) ? 1 : 0, __d);
112 if (_ISNANd(__a))
113 __a = _COPYSIGNd(0, __a);
114 if (_ISNANd(__b))
115 __b = _COPYSIGNd(0, __b);
116 __recalc = 1;
117 }
118 if (!__recalc &&
119 (_ISINFd(__ac) || _ISINFd(__bd) || _ISINFd(__ad) || _ISINFd(__bc))) {
120 if (_ISNANd(__a))
121 __a = _COPYSIGNd(0, __a);
122 if (_ISNANd(__b))
123 __b = _COPYSIGNd(0, __b);
124 if (_ISNANd(__c))
125 __c = _COPYSIGNd(0, __c);
126 if (_ISNANd(__d))
127 __d = _COPYSIGNd(0, __d);
128 __recalc = 1;
129 }
130 if (__recalc) {
131 // Can't use std::numeric_limits<double>::infinity() -- that doesn't have
132 // a device overload (and isn't constexpr before C++11, naturally).
133 __real__(z) = __builtin_huge_val() * (__a * __c - __b * __d);
134 __imag__(z) = __builtin_huge_val() * (__a * __d + __b * __c);
135 }
136 }
137 return z;
138}
139
140__DEVICE__ float _Complex __mulsc3(float __a, float __b, float __c, float __d) {
141 float __ac = __a * __c;
142 float __bd = __b * __d;
143 float __ad = __a * __d;
144 float __bc = __b * __c;
145 float _Complex z;
146 __real__(z) = __ac - __bd;
147 __imag__(z) = __ad + __bc;
148 if (_ISNANf(__real__(z)) && _ISNANf(__imag__(z))) {
149 int __recalc = 0;
150 if (_ISINFf(__a) || _ISINFf(__b)) {
151 __a = _COPYSIGNf(_ISINFf(__a) ? 1 : 0, __a);
152 __b = _COPYSIGNf(_ISINFf(__b) ? 1 : 0, __b);
153 if (_ISNANf(__c))
154 __c = _COPYSIGNf(0, __c);
155 if (_ISNANf(__d))
156 __d = _COPYSIGNf(0, __d);
157 __recalc = 1;
158 }
159 if (_ISINFf(__c) || _ISINFf(__d)) {
160 __c = _COPYSIGNf(_ISINFf(__c) ? 1 : 0, __c);
161 __d = _COPYSIGNf(_ISINFf(__d) ? 1 : 0, __d);
162 if (_ISNANf(__a))
163 __a = _COPYSIGNf(0, __a);
164 if (_ISNANf(__b))
165 __b = _COPYSIGNf(0, __b);
166 __recalc = 1;
167 }
168 if (!__recalc &&
169 (_ISINFf(__ac) || _ISINFf(__bd) || _ISINFf(__ad) || _ISINFf(__bc))) {
170 if (_ISNANf(__a))
171 __a = _COPYSIGNf(0, __a);
172 if (_ISNANf(__b))
173 __b = _COPYSIGNf(0, __b);
174 if (_ISNANf(__c))
175 __c = _COPYSIGNf(0, __c);
176 if (_ISNANf(__d))
177 __d = _COPYSIGNf(0, __d);
178 __recalc = 1;
179 }
180 if (__recalc) {
181 __real__(z) = __builtin_huge_valf() * (__a * __c - __b * __d);
182 __imag__(z) = __builtin_huge_valf() * (__a * __d + __b * __c);
183 }
184 }
185 return z;
186}
187
188__DEVICE__ double _Complex __divdc3(double __a, double __b, double __c,
189 double __d) {
190 int __ilogbw = 0;
191 // Can't use std::max, because that's defined in <algorithm>, and we don't
192 // want to pull that in for every compile. The CUDA headers define
193 // ::max(float, float) and ::max(double, double), which is sufficient for us.
194 double __logbw = _LOGBd(_fmaxd(_ABSd(__c), _ABSd(__d)));
195 if (_ISFINITEd(__logbw)) {
196 __ilogbw = (int)__logbw;
197 __c = _SCALBNd(__c, -__ilogbw);
198 __d = _SCALBNd(__d, -__ilogbw);
199 }
200 double __denom = __c * __c + __d * __d;
201 double _Complex z;
202 __real__(z) = _SCALBNd((__a * __c + __b * __d) / __denom, -__ilogbw);
203 __imag__(z) = _SCALBNd((__b * __c - __a * __d) / __denom, -__ilogbw);
204 if (_ISNANd(__real__(z)) && _ISNANd(__imag__(z))) {
205 if ((__denom == 0.0) && (!_ISNANd(__a) || !_ISNANd(__b))) {
206 __real__(z) = _COPYSIGNd(__builtin_huge_val(), __c) * __a;
207 __imag__(z) = _COPYSIGNd(__builtin_huge_val(), __c) * __b;
208 } else if ((_ISINFd(__a) || _ISINFd(__b)) && _ISFINITEd(__c) &&
209 _ISFINITEd(__d)) {
210 __a = _COPYSIGNd(_ISINFd(__a) ? 1.0 : 0.0, __a);
211 __b = _COPYSIGNd(_ISINFd(__b) ? 1.0 : 0.0, __b);
212 __real__(z) = __builtin_huge_val() * (__a * __c + __b * __d);
213 __imag__(z) = __builtin_huge_val() * (__b * __c - __a * __d);
214 } else if (_ISINFd(__logbw) && __logbw > 0.0 && _ISFINITEd(__a) &&
215 _ISFINITEd(__b)) {
216 __c = _COPYSIGNd(_ISINFd(__c) ? 1.0 : 0.0, __c);
217 __d = _COPYSIGNd(_ISINFd(__d) ? 1.0 : 0.0, __d);
218 __real__(z) = 0.0 * (__a * __c + __b * __d);
219 __imag__(z) = 0.0 * (__b * __c - __a * __d);
220 }
221 }
222 return z;
223}
224
225__DEVICE__ float _Complex __divsc3(float __a, float __b, float __c, float __d) {
226 int __ilogbw = 0;
227 float __logbw = _LOGBf(_fmaxf(_ABSf(__c), _ABSf(__d)));
228 if (_ISFINITEf(__logbw)) {
229 __ilogbw = (int)__logbw;
230 __c = _SCALBNf(__c, -__ilogbw);
231 __d = _SCALBNf(__d, -__ilogbw);
232 }
233 float __denom = __c * __c + __d * __d;
234 float _Complex z;
235 __real__(z) = _SCALBNf((__a * __c + __b * __d) / __denom, -__ilogbw);
236 __imag__(z) = _SCALBNf((__b * __c - __a * __d) / __denom, -__ilogbw);
237 if (_ISNANf(__real__(z)) && _ISNANf(__imag__(z))) {
238 if ((__denom == 0) && (!_ISNANf(__a) || !_ISNANf(__b))) {
239 __real__(z) = _COPYSIGNf(__builtin_huge_valf(), __c) * __a;
240 __imag__(z) = _COPYSIGNf(__builtin_huge_valf(), __c) * __b;
241 } else if ((_ISINFf(__a) || _ISINFf(__b)) && _ISFINITEf(__c) &&
242 _ISFINITEf(__d)) {
243 __a = _COPYSIGNf(_ISINFf(__a) ? 1 : 0, __a);
244 __b = _COPYSIGNf(_ISINFf(__b) ? 1 : 0, __b);
245 __real__(z) = __builtin_huge_valf() * (__a * __c + __b * __d);
246 __imag__(z) = __builtin_huge_valf() * (__b * __c - __a * __d);
247 } else if (_ISINFf(__logbw) && __logbw > 0 && _ISFINITEf(__a) &&
248 _ISFINITEf(__b)) {
249 __c = _COPYSIGNf(_ISINFf(__c) ? 1 : 0, __c);
250 __d = _COPYSIGNf(_ISINFf(__d) ? 1 : 0, __d);
251 __real__(z) = 0 * (__a * __c + __b * __d);
252 __imag__(z) = 0 * (__b * __c - __a * __d);
253 }
254 }
255 return z;
256}
257
258#if defined(__cplusplus)
259} // extern "C"
260#endif
261
262#undef _ISNANd
263#undef _ISNANf
264#undef _ISINFd
265#undef _ISINFf
266#undef _COPYSIGNd
267#undef _COPYSIGNf
268#undef _ISFINITEd
269#undef _ISFINITEf
270#undef _SCALBNd
271#undef _SCALBNf
272#undef _ABSd
273#undef _ABSf
274#undef _LOGBd
275#undef _LOGBf
276#undef _fmaxd
277#undef _fmaxf
278
279#if defined(__OPENMP_NVPTX__) || defined(__OPENMP_AMDGCN__)
280#pragma omp end declare target
281#endif
282
283#pragma pop_macro("__DEVICE__")
284
285#endif // __CLANG_CUDA_COMPLEX_BUILTINS
#define _SCALBNd
#define _COPYSIGNf
#define __DEVICE__
__DEVICE__ double _Complex __divdc3(double __a, double __b, double __c, double __d)
__DEVICE__ double _Complex __muldc3(double __a, double __b, double __c, double __d)
#define _ISFINITEf
#define _COPYSIGNd
__DEVICE__ float _Complex __mulsc3(float __a, float __b, float __c, float __d)
#define _ISFINITEd
#define _SCALBNf
__DEVICE__ float _Complex __divsc3(float __a, float __b, float __c, float __d)
__device__ int
static __inline__ vector float vector float vector float __c
Definition: altivec.h:4800
static __inline__ vector float vector float __b
Definition: altivec.h:578
static __inline__ void int __a
Definition: emmintrin.h:4064