1//===-- include/flang/Evaluate/pgmath.h.inc -------------------------------===//
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// This file defines the interface of libpgmath to be used for folding
10// and code generation.
11// Usage:
12// define PGMATH_DECLARE if you simply want to declare pgmath interface.
13// Define the PGMATH_USE_S/D/C/Z(intrinsic name, function name) according
14// to what needs to be done with the runtime declaration.
15// This intrinsic will be called on all libpgmath function in the
16// intrinsic alphabetical order.
17// Define PGMATH_FAST/RELAXED/PRECISE to restrict the PGMATH_USE visit
18// to the targeted versions.
19// Define PGMATH_USE_OTHER to visit math functions that are not related to
20// floating points (e.g. int**int pow).
21
22// Control Macros
23#ifdef PGMATH_DECLARE
24#undef PGMATH_DECLARE
25#define DEFINE_C_COMPLEX_TYPES
26#define PGMATH_DECLARE(x) extern "C" x;
27#define PGMATH_FAST
28#define PGMATH_PRECISE
29#define PGMATH_RELAXED
30#else
31#define PGMATH_DECLARE(x)
32#endif
33
34#ifdef PGMATH_USE_ALL_TYPES
35#define PGMATH_USE_S(name, func) PGMATH_USE_ALL_TYPES(name, func)
36#define PGMATH_USE_D(name, func) PGMATH_USE_ALL_TYPES(name, func)
37#define PGMATH_USE_C(name, func) PGMATH_USE_ALL_TYPES(name, func)
38#define PGMATH_USE_Z(name, func) PGMATH_USE_ALL_TYPES(name, func)
39#define PGMATH_USE_OTHER(name, func) PGMATH_USE_ALL_TYPES(name, func)
40#endif
41
42#ifndef PGMATH_USE_S
43#define PGMATH_USE_S(name, x)
44#endif
45
46#ifndef PGMATH_USE_D
47#define PGMATH_USE_D(name, x)
48#endif
49
50#ifndef PGMATH_USE_C
51#define PGMATH_USE_C(name, x)
52#endif
53
54#ifndef PGMATH_USE_Z
55#define PGMATH_USE_Z(name, x)
56#endif
57
58#ifndef PGMATH_USE_OTHER
59#define PGMATH_USE_OTHER(name, x)
60#endif
61
62// Handle the C99 _Complex vs C++ std::complex call interface issue.
63// _Complex and std::complex are layout compatible (they are the same when
64// in memory), but they are not guaranteed to be compatible in call interface
65// (they may be passed/returned differently). For instance on X86 32 bits,
66// float _complex is returned in a pair of register, but std::complex<float>
67// is returned in memory.
68// Pgmath is defined in C using _Complex (and windows _Fcomplex/_DComplex
69// equivalents). Since this file defines the call interface with the runtime
70// for both folding and code generation (through template introspection), it
71// is crucial to make a distinction between std::complex and _Complex here.
72// Unfortunately, _Complex support is not standard in C++.
73// Reserve pgmath usage at compile time (folding) when _Complex is available
74// (cmake is responsible to detect this).
75// For code generation, define type c_float_complex_t that can be used in
76// introspection to indicate that the C99 _Complex ABI has to be used for the
77// related value.
78#ifdef DEFINE_C_COMPLEX_TYPES
79#ifdef PGMATH_LINKING
80#ifdef _WIN32
81using c_float_complex_t = _Fcomplex;
82using c_double_complex_t = _Dcomplex;
83#else
84using c_float_complex_t = float _Complex;
85using c_double_complex_t = double _Complex;
86#endif
87#else
88struct c_float_complex_t {};
89struct c_double_complex_t {};
90#endif
91#endif
92
93#define PGMATH_REAL_IMPL(impl, func) \
94  PGMATH_DECLARE(float __##impl##s_##func##_1(float)) \
95  PGMATH_DECLARE(double __##impl##d_##func##_1(double)) \
96  PGMATH_USE_S(func, __##impl##s_##func##_1) \
97  PGMATH_USE_D(func, __##impl##d_##func##_1)
98
99#define PGMATH_COMPLEX_IMPL(impl, func) \
100  PGMATH_DECLARE(c_float_complex_t __##impl##c_##func##_1(c_float_complex_t)) \
101  PGMATH_DECLARE( \
102      c_double_complex_t __##impl##z_##func##_1(c_double_complex_t)) \
103  PGMATH_USE_C(func, __##impl##c_##func##_1) \
104  PGMATH_USE_Z(func, __##impl##z_##func##_1)
105
106#define PGMATH_ALL_FP_IMPL(impl, func) \
107  PGMATH_REAL_IMPL(impl, func) \
108  PGMATH_FAST_COMPLEX_IMPL(impl, func)
109
110#define PGMATH_REAL2_IMPL(impl, func) \
111  PGMATH_DECLARE(float __##impl##s_##func##_1(float, float)) \
112  PGMATH_DECLARE(double __##impl##d_##func##_1(double, double)) \
113  PGMATH_USE_S(func, __##impl##s_##func##_1) \
114  PGMATH_USE_D(func, __##impl##d_##func##_1)
115
116#define PGMATH_COMPLEX2_IMPL(impl, func) \
117  PGMATH_DECLARE(c_float_complex_t __##impl##c_##func##_1( \
118      c_float_complex_t, c_float_complex_t)) \
119  PGMATH_DECLARE(c_double_complex_t __##impl##z_##func##_1( \
120      c_double_complex_t, c_double_complex_t)) \
121  PGMATH_USE_C(func, __##impl##c_##func##_1) \
122  PGMATH_USE_Z(func, __##impl##z_##func##_1)
123
124#define PGMATH_ALL_FP2_IMPL(impl, func) \
125  PGMATH_REAL2_IMPL(func) \
126  PGMATH_COMPLEX2_IMPL(func)
127
128#undef PGMATH_FAST_REAL
129#undef PGMATH_FAST_COMPLEX
130#undef PGMATH_FAST_ALL_FP
131#undef PGMATH_FAST_REAL2
132#undef PGMATH_FAST_COMPLEX2
133#undef PGMATH_FAST_ALL_FP2
134#ifdef PGMATH_FAST
135#define PGMATH_FAST_REAL(func) PGMATH_REAL_IMPL(f, func)
136#define PGMATH_FAST_COMPLEX(func) PGMATH_COMPLEX_IMPL(f, func)
137#define PGMATH_FAST_ALL_FP(func) PGMATH_ALL_IMPL(f, func)
138#define PGMATH_FAST_REAL2(func) PGMATH_REAL2_IMPL(f, func)
139#define PGMATH_FAST_COMPLEX2(func) PGMATH_COMPLEX2_IMPL(f, func)
140#define PGMATH_FAST_ALL_FP2(func) PGMATH_ALL_FP2_IMPL(f, func)
141#else
142#define PGMATH_FAST_REAL(func)
143#define PGMATH_FAST_COMPLEX(func)
144#define PGMATH_FAST_ALL_FP(func)
145#define PGMATH_FAST_REAL2(func)
146#define PGMATH_FAST_COMPLEX2(func)
147#define PGMATH_FAST_ALL_FP2(func)
148#endif
149
150#undef PGMATH_RELAXED_REAL
151#undef PGMATH_RELAXED_COMPLEX
152#undef PGMATH_RELAXED_ALL_FP
153#undef PGMATH_RELAXED_REAL2
154#undef PGMATH_RELAXED_COMPLEX2
155#undef PGMATH_RELAXED_ALL_FP2
156#ifdef PGMATH_RELAXED
157#define PGMATH_RELAXED_REAL(func) PGMATH_REAL_IMPL(r, func)
158#define PGMATH_RELAXED_COMPLEX(func) PGMATH_COMPLEX_IMPL(r, func)
159#define PGMATH_RELAXED_ALL_FP(func) PGMATH_ALL_IMPL(r, func)
160#define PGMATH_RELAXED_REAL2(func) PGMATH_REAL2_IMPL(r, func)
161#define PGMATH_RELAXED_COMPLEX2(func) PGMATH_COMPLEX2_IMPL(r, func)
162#define PGMATH_RELAXED_ALL_FP2(func) PGMATH_ALL_FP2_IMPL(r, func)
163#else
164#define PGMATH_RELAXED_REAL(func)
165#define PGMATH_RELAXED_COMPLEX(func)
166#define PGMATH_RELAXED_ALL_FP(func)
167#define PGMATH_RELAXED_REAL2(func)
168#define PGMATH_RELAXED_COMPLEX2(func)
169#define PGMATH_RELAXED_ALL_FP2(func)
170#endif
171
172#undef PGMATH_PRECISE_REAL
173#undef PGMATH_PRECISE_COMPLEX
174#undef PGMATH_PRECISE_ALL_FP
175#undef PGMATH_PRECISE_REAL2
176#undef PGMATH_PRECISE_COMPLEX2
177#undef PGMATH_PRECISE_ALL_FP2
178#ifdef PGMATH_PRECISE
179#define PGMATH_PRECISE_REAL(func) PGMATH_REAL_IMPL(p, func)
180#define PGMATH_PRECISE_COMPLEX(func) PGMATH_COMPLEX_IMPL(p, func)
181#define PGMATH_PRECISE_ALL_FP(func) PGMATH_ALL_IMPL(p, func)
182#define PGMATH_PRECISE_REAL2(func) PGMATH_REAL2_IMPL(p, func)
183#define PGMATH_PRECISE_COMPLEX2(func) PGMATH_COMPLEX2_IMPL(p, func)
184#define PGMATH_PRECISE_ALL_FP2(func) PGMATH_ALL_FP2_IMPL(p, func)
185#else
186#define PGMATH_PRECISE_REAL(func)
187#define PGMATH_PRECISE_COMPLEX(func)
188#define PGMATH_PRECISE_ALL_FP(func)
189#define PGMATH_PRECISE_REAL2(func)
190#define PGMATH_PRECISE_COMPLEX2(func)
191#define PGMATH_PRECISE_ALL_FP2(func)
192#endif
193
194#define PGMATH_REAL(func) \
195  PGMATH_FAST_REAL(func) \
196  PGMATH_PRECISE_REAL(func) \
197  PGMATH_RELAXED_REAL(func)
198
199#define PGMATH_COMPLEX(func) \
200  PGMATH_FAST_COMPLEX(func) \
201  PGMATH_PRECISE_COMPLEX(func) \
202  PGMATH_RELAXED_COMPLEX(func)
203
204#define PGMATH_ALL(func) \
205  PGMATH_REAL(func) \
206  PGMATH_COMPLEX(func)
207
208#define PGMATH_REAL2(func) \
209  PGMATH_FAST_REAL2(func) \
210  PGMATH_PRECISE_REAL2(func) \
211  PGMATH_RELAXED_REAL2(func)
212
213#define PGMATH_COMPLEX2(func) \
214  PGMATH_FAST_COMPLEX2(func) \
215  PGMATH_PRECISE_COMPLEX2(func) \
216  PGMATH_RELAXED_COMPLEX2(func)
217
218#define PGMATH_ALL2(func) \
219  PGMATH_REAL2(func) \
220  PGMATH_COMPLEX2(func)
221
222// Marcos to declare __mth_i libpgmath variants
223#define PGMATH_MTH_VERSION_REAL(func) \
224  PGMATH_DECLARE(float __mth_i_##func(float)) \
225  PGMATH_DECLARE(double __mth_i_d##func(double)) \
226  PGMATH_USE_S(func, __mth_i_##func) \
227  PGMATH_USE_D(func, __mth_i_d##func)
228
229// Actual libpgmath declarations
230PGMATH_ALL(acos)
231PGMATH_MTH_VERSION_REAL(acosh)
232PGMATH_ALL(asin)
233PGMATH_MTH_VERSION_REAL(asinh)
234PGMATH_ALL(atan)
235PGMATH_REAL2(atan2)
236PGMATH_MTH_VERSION_REAL(atanh)
237PGMATH_MTH_VERSION_REAL(bessel_j0)
238PGMATH_MTH_VERSION_REAL(bessel_j1)
239// bessel_jn and bessel_yn takes an int as first arg
240PGMATH_DECLARE(float __mth_i_bessel_jn(int, float))
241PGMATH_DECLARE(double __mth_i_dbessel_jn(int, double))
242PGMATH_USE_S(bessel_jn, __mth_i_bessel_jn)
243PGMATH_USE_D(bessel_jn, __mth_i_dbessel_jn)
244PGMATH_MTH_VERSION_REAL(bessel_y0)
245PGMATH_MTH_VERSION_REAL(bessel_y1)
246PGMATH_DECLARE(float __mth_i_bessel_yn(int, float))
247PGMATH_DECLARE(double __mth_i_dbessel_yn(int, double))
248PGMATH_USE_S(bessel_yn, __mth_i_bessel_yn)
249PGMATH_USE_D(bessel_yn, __mth_i_dbessel_yn)
250
251PGMATH_ALL(cos)
252PGMATH_ALL(cosh)
253PGMATH_MTH_VERSION_REAL(erf)
254PGMATH_MTH_VERSION_REAL(erfc)
255PGMATH_MTH_VERSION_REAL(erfc_scaled)
256PGMATH_ALL(exp)
257PGMATH_MTH_VERSION_REAL(gamma)
258
259PGMATH_DECLARE(float __mth_i_hypot(float, float))
260PGMATH_DECLARE(double __mth_i_dhypot(double, double))
261PGMATH_USE_S(hypot, __mth_i_hypot)
262PGMATH_USE_D(hypot, __mth_i_dhypot)
263
264PGMATH_ALL(log)
265PGMATH_REAL(log10)
266PGMATH_MTH_VERSION_REAL(log_gamma)
267// no function for modulo in libpgmath.
268// fast mod used in all versions.
269PGMATH_DECLARE(float __fs_mod_1(float, float))
270PGMATH_DECLARE(double __fd_mod_1(double, double))
271PGMATH_USE_S(mod, __fs_mod_1)
272PGMATH_USE_D(mod, __fd_mod_1)
273
274PGMATH_ALL2(pow)
275// Versions of pow with integer exponents
276#define PGMATH_DELCARE_POW(impl) \
277  PGMATH_DECLARE(float __##impl##s_powi_1(float, int)) \
278  PGMATH_DECLARE(double __##impl##d_powi_1(double, int)) \
279  PGMATH_DECLARE(c_float_complex_t __##impl##c_powi_1(c_float_complex_t, int)) \
280  PGMATH_DECLARE( \
281      c_double_complex_t __##impl##z_powi_1(c_double_complex_t, int)) \
282  PGMATH_USE_S(pow, __##impl##s_powi_1) \
283  PGMATH_USE_D(pow, __##impl##d_powi_1) \
284  PGMATH_USE_C(pow, __##impl##c_powi_1) \
285  PGMATH_USE_Z(pow, __##impl##z_powi_1) \
286  PGMATH_DECLARE(float __##impl##s_powk_1(float, int64_t)) \
287  PGMATH_DECLARE(double __##impl##d_powk_1(double, int64_t)) \
288  PGMATH_DECLARE( \
289      c_float_complex_t __##impl##c_powk_1(c_float_complex_t, int64_t)) \
290  PGMATH_DECLARE( \
291      c_double_complex_t __##impl##z_powk_1(c_double_complex_t, int64_t)) \
292  PGMATH_USE_S(pow, __##impl##s_powk_1) \
293  PGMATH_USE_D(pow, __##impl##d_powk_1) \
294  PGMATH_USE_C(pow, __##impl##c_powk_1) \
295  PGMATH_USE_Z(pow, __##impl##z_powk_1)
296
297#ifdef PGMATH_FAST
298PGMATH_DELCARE_POW(f)
299#endif
300#ifdef PGMATH_RELAXED
301PGMATH_DELCARE_POW(r)
302#endif
303#ifdef PGMATH_PRECISE
304PGMATH_DELCARE_POW(p)
305#endif
306
307// integer ** integer versions of pow
308PGMATH_DECLARE(int __mth_i_ipowi(int, int))
309PGMATH_DECLARE(int64_t __mth_i_kpowk(int64_t, int64_t))
310PGMATH_USE_OTHER(pow, __mth_i_ipowi)
311PGMATH_USE_OTHER(pow, __mth_i_kpowk)
312
313PGMATH_ALL(sin)
314PGMATH_ALL(sinh)
315PGMATH_MTH_VERSION_REAL(sqrt)
316PGMATH_COMPLEX(sqrt) // real versions are __mth_i...
317PGMATH_ALL(tan)
318PGMATH_ALL(tanh)
319
320#undef PGMATH_DECLARE
321#undef PGMATH_FAST
322#undef PGMATH_PRECISE
323#undef PGMATH_RELAXED
324#undef PGMATH_USE_S
325#undef PGMATH_USE_D
326#undef PGMATH_USE_C
327#undef PGMATH_USE_Z
328#undef PGMATH_USE_OTHER
329#undef PGMATH_USE_ALL_TYPES
330#undef PGMATH_LINKING
331#undef DEFINE_C_COMPLEX_TYPES
332