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