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

source code of flang-rt/lib/quadmath/math-entries.h