1 //===-- runtime/Float128Math/math-entries.h ---------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef FORTRAN_RUNTIME_FLOAT128MATH_MATH_ENTRIES_H_
10 #define FORTRAN_RUNTIME_FLOAT128MATH_MATH_ENTRIES_H_
11 #include "terminator.h"
13 #include "flang/Common/float128.h"
14 #include "flang/Runtime/entry-names.h"
17 #include <type_traits>
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>;
26 namespace Fortran::runtime
{
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
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); \
40 // Define template specialization that is calling the third-party
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>) { \
55 return callee(args...); \
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)
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
)
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
)
161 // Use cmath INFINITY/NAN definition. Rely on C implicit conversions.
162 #define F128_RT_INFINITY (INFINITY)
163 #define F128_RT_QNAN (NAN)
165 // Define wrapper callers for libm.
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
)
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
)
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())
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"
232 } // namespace Fortran::runtime
234 #endif // FORTRAN_RUNTIME_FLOAT128MATH_MATH_ENTRIES_H_