1 //===-- runtime/Float128Math/math-entries.h ---------------------*- C++ -*-===// 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 #ifndef FORTRAN_RUNTIME_FLOAT128MATH_MATH_ENTRIES_H_ 10 #define FORTRAN_RUNTIME_FLOAT128MATH_MATH_ENTRIES_H_ 11 #include "terminator.h" 12 #include "tools.h" 13 #include "flang/Common/float128.h" 14 #include "flang/Runtime/entry-names.h" 15 #include <cfloat> 16 #include <cmath> 17 #include <type_traits> 18 19 namespace { 20 using namespace Fortran::runtime; 21 using F128RetType = CppTypeFor<TypeCategory::Real, 16>; 22 using I32RetType = CppTypeFor<TypeCategory::Integer, 4>; 23 using I64RetType = CppTypeFor<TypeCategory::Integer, 8>; 24 } // namespace 25 26 namespace Fortran::runtime { 27 28 // Define a class template to gracefully fail, when 29 // there is no specialized template that implements 30 // the required function via using the third-party 31 // implementation. 32 #define DEFINE_FALLBACK(caller, ret_type) \ 33 template <bool = false, typename RT = ret_type> struct caller { \ 34 template <typename... ATs> [[noreturn]] static RT invoke(ATs... args) { \ 35 Terminator terminator{__FILE__, __LINE__}; \ 36 terminator.Crash("Float128 variant of '%s' is unsupported", #caller); \ 37 } \ 38 }; 39 40 // Define template specialization that is calling the third-party 41 // implementation. 42 // 43 // Defining the specialization for any target library requires 44 // adding the generic template via DEFINE_FALLBACK, so that 45 // a build with another target library that does not define 46 // the same alias can gracefully fail in runtime. 47 #define DEFINE_SIMPLE_ALIAS(caller, callee) \ 48 template <typename RT> struct caller<true, RT> { \ 49 template <typename... ATs> static RT invoke(ATs... args) { \ 50 static_assert(std::is_invocable_r_v<RT, \ 51 decltype(callee(std::declval<ATs>()...))(ATs...), ATs...>); \ 52 if constexpr (std::is_same_v<RT, void>) { \ 53 callee(args...); \ 54 } else { \ 55 return callee(args...); \ 56 } \ 57 } \ 58 }; 59 60 // Define fallback callers. 61 #define DEFINE_FALLBACK_F128(caller) DEFINE_FALLBACK(caller, ::F128RetType) 62 #define DEFINE_FALLBACK_I32(caller) DEFINE_FALLBACK(caller, ::I32RetType) 63 #define DEFINE_FALLBACK_I64(caller) DEFINE_FALLBACK(caller, ::I64RetType) 64 65 DEFINE_FALLBACK_F128(Abs) 66 DEFINE_FALLBACK_F128(Acos) 67 DEFINE_FALLBACK_F128(Acosh) 68 DEFINE_FALLBACK_F128(Asin) 69 DEFINE_FALLBACK_F128(Asinh) 70 DEFINE_FALLBACK_F128(Atan) 71 DEFINE_FALLBACK_F128(Atan2) 72 DEFINE_FALLBACK_F128(Atanh) 73 DEFINE_FALLBACK_F128(Ceil) 74 DEFINE_FALLBACK_F128(Cos) 75 DEFINE_FALLBACK_F128(Cosh) 76 DEFINE_FALLBACK_F128(Erf) 77 DEFINE_FALLBACK_F128(Erfc) 78 DEFINE_FALLBACK_F128(Exp) 79 DEFINE_FALLBACK_F128(Floor) 80 DEFINE_FALLBACK_F128(Fma) 81 DEFINE_FALLBACK_F128(Frexp) 82 DEFINE_FALLBACK_F128(Hypot) 83 DEFINE_FALLBACK_I32(Ilogb) 84 DEFINE_FALLBACK_I32(Isinf) 85 DEFINE_FALLBACK_I32(Isnan) 86 DEFINE_FALLBACK_F128(J0) 87 DEFINE_FALLBACK_F128(J1) 88 DEFINE_FALLBACK_F128(Jn) 89 DEFINE_FALLBACK_F128(Ldexp) 90 DEFINE_FALLBACK_F128(Lgamma) 91 DEFINE_FALLBACK_I64(Llround) 92 DEFINE_FALLBACK_F128(Log) 93 DEFINE_FALLBACK_F128(Log10) 94 DEFINE_FALLBACK_I32(Lround) 95 DEFINE_FALLBACK_F128(Nearbyint) 96 DEFINE_FALLBACK_F128(Nextafter) 97 DEFINE_FALLBACK_F128(Pow) 98 DEFINE_FALLBACK_F128(Qnan) 99 DEFINE_FALLBACK_F128(Remainder) 100 DEFINE_FALLBACK_F128(Round) 101 DEFINE_FALLBACK_F128(Sin) 102 DEFINE_FALLBACK_F128(Sinh) 103 DEFINE_FALLBACK_F128(Sqrt) 104 DEFINE_FALLBACK_F128(Tan) 105 DEFINE_FALLBACK_F128(Tanh) 106 DEFINE_FALLBACK_F128(Tgamma) 107 DEFINE_FALLBACK_F128(Trunc) 108 DEFINE_FALLBACK_F128(Y0) 109 DEFINE_FALLBACK_F128(Y1) 110 DEFINE_FALLBACK_F128(Yn) 111 112 #if HAS_QUADMATHLIB 113 // Define wrapper callers for libquadmath. 114 #include "quadmath.h" 115 DEFINE_SIMPLE_ALIAS(Abs, fabsq) 116 DEFINE_SIMPLE_ALIAS(Acos, acosq) 117 DEFINE_SIMPLE_ALIAS(Acosh, acoshq) 118 DEFINE_SIMPLE_ALIAS(Asin, asinq) 119 DEFINE_SIMPLE_ALIAS(Asinh, asinhq) 120 DEFINE_SIMPLE_ALIAS(Atan, atanq) 121 DEFINE_SIMPLE_ALIAS(Atan2, atan2q) 122 DEFINE_SIMPLE_ALIAS(Atanh, atanhq) 123 DEFINE_SIMPLE_ALIAS(Ceil, ceilq) 124 DEFINE_SIMPLE_ALIAS(Cos, cosq) 125 DEFINE_SIMPLE_ALIAS(Cosh, coshq) 126 DEFINE_SIMPLE_ALIAS(Erf, erfq) 127 DEFINE_SIMPLE_ALIAS(Erfc, erfcq) 128 DEFINE_SIMPLE_ALIAS(Exp, expq) 129 DEFINE_SIMPLE_ALIAS(Floor, floorq) 130 DEFINE_SIMPLE_ALIAS(Fma, fmaq) 131 DEFINE_SIMPLE_ALIAS(Frexp, frexpq) 132 DEFINE_SIMPLE_ALIAS(Hypot, hypotq) 133 DEFINE_SIMPLE_ALIAS(Ilogb, ilogbq) 134 DEFINE_SIMPLE_ALIAS(Isinf, isinfq) 135 DEFINE_SIMPLE_ALIAS(Isnan, isnanq) 136 DEFINE_SIMPLE_ALIAS(J0, j0q) 137 DEFINE_SIMPLE_ALIAS(J1, j1q) 138 DEFINE_SIMPLE_ALIAS(Jn, jnq) 139 DEFINE_SIMPLE_ALIAS(Ldexp, ldexpq) 140 DEFINE_SIMPLE_ALIAS(Lgamma, lgammaq) 141 DEFINE_SIMPLE_ALIAS(Llround, llroundq) 142 DEFINE_SIMPLE_ALIAS(Log, logq) 143 DEFINE_SIMPLE_ALIAS(Log10, log10q) 144 DEFINE_SIMPLE_ALIAS(Lround, lroundq) 145 DEFINE_SIMPLE_ALIAS(Nearbyint, nearbyintq) 146 DEFINE_SIMPLE_ALIAS(Nextafter, nextafterq) 147 DEFINE_SIMPLE_ALIAS(Pow, powq) 148 DEFINE_SIMPLE_ALIAS(Remainder, remainderq) 149 DEFINE_SIMPLE_ALIAS(Round, roundq) 150 DEFINE_SIMPLE_ALIAS(Sin, sinq) 151 DEFINE_SIMPLE_ALIAS(Sinh, sinhq) 152 DEFINE_SIMPLE_ALIAS(Sqrt, sqrtq) 153 DEFINE_SIMPLE_ALIAS(Tan, tanq) 154 DEFINE_SIMPLE_ALIAS(Tanh, tanhq) 155 DEFINE_SIMPLE_ALIAS(Tgamma, tgammaq) 156 DEFINE_SIMPLE_ALIAS(Trunc, truncq) 157 DEFINE_SIMPLE_ALIAS(Y0, y0q) 158 DEFINE_SIMPLE_ALIAS(Y1, y1q) 159 DEFINE_SIMPLE_ALIAS(Yn, ynq) 160 161 // Use cmath INFINITY/NAN definition. Rely on C implicit conversions. 162 #define F128_RT_INFINITY (INFINITY) 163 #define F128_RT_QNAN (NAN) 164 #elif HAS_LDBL128 165 // Define wrapper callers for libm. 166 #include <limits> 167 168 // Use STD math functions. They provide IEEE-754 128-bit float 169 // support either via 'long double' or __float128. 170 // The Bessel's functions are not present in STD namespace. 171 DEFINE_SIMPLE_ALIAS(Abs, std::abs) 172 DEFINE_SIMPLE_ALIAS(Acos, std::acos) 173 DEFINE_SIMPLE_ALIAS(Acosh, std::acosh) 174 DEFINE_SIMPLE_ALIAS(Asin, std::asin) 175 DEFINE_SIMPLE_ALIAS(Asinh, std::asinh) 176 DEFINE_SIMPLE_ALIAS(Atan, std::atan) 177 DEFINE_SIMPLE_ALIAS(Atan2, std::atan2) 178 DEFINE_SIMPLE_ALIAS(Atanh, std::atanh) 179 DEFINE_SIMPLE_ALIAS(Ceil, std::ceil) 180 DEFINE_SIMPLE_ALIAS(Cos, std::cos) 181 DEFINE_SIMPLE_ALIAS(Cosh, std::cosh) 182 DEFINE_SIMPLE_ALIAS(Erf, std::erf) 183 DEFINE_SIMPLE_ALIAS(Erfc, std::erfc) 184 DEFINE_SIMPLE_ALIAS(Exp, std::exp) 185 DEFINE_SIMPLE_ALIAS(Floor, std::floor) 186 DEFINE_SIMPLE_ALIAS(Fma, std::fma) 187 DEFINE_SIMPLE_ALIAS(Frexp, std::frexp) 188 DEFINE_SIMPLE_ALIAS(Hypot, std::hypot) 189 DEFINE_SIMPLE_ALIAS(Ilogb, std::ilogb) 190 DEFINE_SIMPLE_ALIAS(Isinf, std::isinf) 191 DEFINE_SIMPLE_ALIAS(Isnan, std::isnan) 192 DEFINE_SIMPLE_ALIAS(Ldexp, std::ldexp) 193 DEFINE_SIMPLE_ALIAS(Lgamma, std::lgamma) 194 DEFINE_SIMPLE_ALIAS(Llround, std::llround) 195 DEFINE_SIMPLE_ALIAS(Log, std::log) 196 DEFINE_SIMPLE_ALIAS(Log10, std::log10) 197 DEFINE_SIMPLE_ALIAS(Lround, std::lround) 198 DEFINE_SIMPLE_ALIAS(Nearbyint, std::nearbyint) 199 DEFINE_SIMPLE_ALIAS(Nextafter, std::nextafter) 200 DEFINE_SIMPLE_ALIAS(Pow, std::pow) 201 DEFINE_SIMPLE_ALIAS(Remainder, std::remainder) 202 DEFINE_SIMPLE_ALIAS(Round, std::round) 203 DEFINE_SIMPLE_ALIAS(Sin, std::sin) 204 DEFINE_SIMPLE_ALIAS(Sinh, std::sinh) 205 DEFINE_SIMPLE_ALIAS(Sqrt, std::sqrt) 206 DEFINE_SIMPLE_ALIAS(Tan, std::tan) 207 DEFINE_SIMPLE_ALIAS(Tanh, std::tanh) 208 DEFINE_SIMPLE_ALIAS(Tgamma, std::tgamma) 209 DEFINE_SIMPLE_ALIAS(Trunc, std::trunc) 210 211 #if defined(__GLIBC__) && defined(_GNU_SOURCE) 212 DEFINE_SIMPLE_ALIAS(J0, j0l) 213 DEFINE_SIMPLE_ALIAS(J1, j1l) 214 DEFINE_SIMPLE_ALIAS(Jn, jnl) 215 DEFINE_SIMPLE_ALIAS(Y0, y0l) 216 DEFINE_SIMPLE_ALIAS(Y1, y1l) 217 DEFINE_SIMPLE_ALIAS(Yn, ynl) 218 #endif 219 220 // Use numeric_limits to produce infinity of the right type. 221 #define F128_RT_INFINITY \ 222 (std::numeric_limits<CppTypeFor<TypeCategory::Real, 16>>::infinity()) 223 #define F128_RT_QNAN \ 224 (std::numeric_limits<CppTypeFor<TypeCategory::Real, 16>>::quiet_NaN()) 225 #elif HAS_LIBMF128 226 // We can use __float128 versions of libm functions. 227 // __STDC_WANT_IEC_60559_TYPES_EXT__ needs to be defined 228 // before including cmath to enable the *f128 prototypes. 229 #error "Float128Math build with glibc>=2.26 is unsupported yet" 230 #endif 231 232 } // namespace Fortran::runtime 233 234 #endif // FORTRAN_RUNTIME_FLOAT128MATH_MATH_ENTRIES_H_ 235