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
19namespace {
20using namespace Fortran::runtime;
21using F128RetType = CppTypeFor<TypeCategory::Real, 16>;
22using I32RetType = CppTypeFor<TypeCategory::Integer, 4>;
23using I64RetType = CppTypeFor<TypeCategory::Integer, 8>;
24} // namespace
25
26namespace 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
65DEFINE_FALLBACK_F128(Abs)
66DEFINE_FALLBACK_F128(Acos)
67DEFINE_FALLBACK_F128(Acosh)
68DEFINE_FALLBACK_F128(Asin)
69DEFINE_FALLBACK_F128(Asinh)
70DEFINE_FALLBACK_F128(Atan)
71DEFINE_FALLBACK_F128(Atan2)
72DEFINE_FALLBACK_F128(Atanh)
73DEFINE_FALLBACK_F128(Ceil)
74DEFINE_FALLBACK_F128(Cos)
75DEFINE_FALLBACK_F128(Cosh)
76DEFINE_FALLBACK_F128(Erf)
77DEFINE_FALLBACK_F128(Erfc)
78DEFINE_FALLBACK_F128(Exp)
79DEFINE_FALLBACK_F128(Floor)
80DEFINE_FALLBACK_F128(Fma)
81DEFINE_FALLBACK_F128(Frexp)
82DEFINE_FALLBACK_F128(Hypot)
83DEFINE_FALLBACK_I32(Ilogb)
84DEFINE_FALLBACK_I32(Isinf)
85DEFINE_FALLBACK_I32(Isnan)
86DEFINE_FALLBACK_F128(J0)
87DEFINE_FALLBACK_F128(J1)
88DEFINE_FALLBACK_F128(Jn)
89DEFINE_FALLBACK_F128(Ldexp)
90DEFINE_FALLBACK_F128(Lgamma)
91DEFINE_FALLBACK_I64(Llround)
92DEFINE_FALLBACK_F128(Log)
93DEFINE_FALLBACK_F128(Log10)
94DEFINE_FALLBACK_I32(Lround)
95DEFINE_FALLBACK_F128(Nextafter)
96DEFINE_FALLBACK_F128(Pow)
97DEFINE_FALLBACK_F128(Qnan)
98DEFINE_FALLBACK_F128(Round)
99DEFINE_FALLBACK_F128(Sin)
100DEFINE_FALLBACK_F128(Sinh)
101DEFINE_FALLBACK_F128(Sqrt)
102DEFINE_FALLBACK_F128(Tan)
103DEFINE_FALLBACK_F128(Tanh)
104DEFINE_FALLBACK_F128(Tgamma)
105DEFINE_FALLBACK_F128(Trunc)
106DEFINE_FALLBACK_F128(Y0)
107DEFINE_FALLBACK_F128(Y1)
108DEFINE_FALLBACK_F128(Yn)
109
110#if HAS_QUADMATHLIB
111// Define wrapper callers for libquadmath.
112#include "quadmath.h"
113DEFINE_SIMPLE_ALIAS(Abs, fabsq)
114DEFINE_SIMPLE_ALIAS(Acos, acosq)
115DEFINE_SIMPLE_ALIAS(Acosh, acoshq)
116DEFINE_SIMPLE_ALIAS(Asin, asinq)
117DEFINE_SIMPLE_ALIAS(Asinh, asinhq)
118DEFINE_SIMPLE_ALIAS(Atan, atanq)
119DEFINE_SIMPLE_ALIAS(Atan2, atan2q)
120DEFINE_SIMPLE_ALIAS(Atanh, atanhq)
121DEFINE_SIMPLE_ALIAS(Ceil, ceilq)
122DEFINE_SIMPLE_ALIAS(Cos, cosq)
123DEFINE_SIMPLE_ALIAS(Cosh, coshq)
124DEFINE_SIMPLE_ALIAS(Erf, erfq)
125DEFINE_SIMPLE_ALIAS(Erfc, erfcq)
126DEFINE_SIMPLE_ALIAS(Exp, expq)
127DEFINE_SIMPLE_ALIAS(Floor, floorq)
128DEFINE_SIMPLE_ALIAS(Fma, fmaq)
129DEFINE_SIMPLE_ALIAS(Frexp, frexpq)
130DEFINE_SIMPLE_ALIAS(Hypot, hypotq)
131DEFINE_SIMPLE_ALIAS(Ilogb, ilogbq)
132DEFINE_SIMPLE_ALIAS(Isinf, isinfq)
133DEFINE_SIMPLE_ALIAS(Isnan, isnanq)
134DEFINE_SIMPLE_ALIAS(J0, j0q)
135DEFINE_SIMPLE_ALIAS(J1, j1q)
136DEFINE_SIMPLE_ALIAS(Jn, jnq)
137DEFINE_SIMPLE_ALIAS(Ldexp, ldexpq)
138DEFINE_SIMPLE_ALIAS(Lgamma, lgammaq)
139DEFINE_SIMPLE_ALIAS(Llround, llroundq)
140DEFINE_SIMPLE_ALIAS(Log, logq)
141DEFINE_SIMPLE_ALIAS(Log10, log10q)
142DEFINE_SIMPLE_ALIAS(Lround, lroundq)
143DEFINE_SIMPLE_ALIAS(Nextafter, nextafterq)
144DEFINE_SIMPLE_ALIAS(Pow, powq)
145DEFINE_SIMPLE_ALIAS(Round, roundq)
146DEFINE_SIMPLE_ALIAS(Sin, sinq)
147DEFINE_SIMPLE_ALIAS(Sinh, sinhq)
148DEFINE_SIMPLE_ALIAS(Sqrt, sqrtq)
149DEFINE_SIMPLE_ALIAS(Tan, tanq)
150DEFINE_SIMPLE_ALIAS(Tanh, tanhq)
151DEFINE_SIMPLE_ALIAS(Tgamma, tgammaq)
152DEFINE_SIMPLE_ALIAS(Trunc, truncq)
153DEFINE_SIMPLE_ALIAS(Y0, y0q)
154DEFINE_SIMPLE_ALIAS(Y1, y1q)
155DEFINE_SIMPLE_ALIAS(Yn, ynq)
156
157// Use cmath INFINITY/NAN definition. Rely on C implicit conversions.
158#define F128_RT_INFINITY (INFINITY)
159#define F128_RT_QNAN (NAN)
160#elif LDBL_MANT_DIG == 113
161// Define wrapper callers for libm.
162#include <limits>
163
164// Use STD math functions. They provide IEEE-754 128-bit float
165// support either via 'long double' or __float128.
166// The Bessel's functions are not present in STD namespace.
167DEFINE_SIMPLE_ALIAS(Abs, std::abs)
168DEFINE_SIMPLE_ALIAS(Acos, std::acos)
169DEFINE_SIMPLE_ALIAS(Acosh, std::acosh)
170DEFINE_SIMPLE_ALIAS(Asin, std::asin)
171DEFINE_SIMPLE_ALIAS(Asinh, std::asinh)
172DEFINE_SIMPLE_ALIAS(Atan, std::atan)
173DEFINE_SIMPLE_ALIAS(Atan2, std::atan2)
174DEFINE_SIMPLE_ALIAS(Atanh, std::atanh)
175DEFINE_SIMPLE_ALIAS(Ceil, std::ceil)
176DEFINE_SIMPLE_ALIAS(Cos, std::cos)
177DEFINE_SIMPLE_ALIAS(Cosh, std::cosh)
178DEFINE_SIMPLE_ALIAS(Erf, std::erf)
179DEFINE_SIMPLE_ALIAS(Erfc, std::erfc)
180DEFINE_SIMPLE_ALIAS(Exp, std::exp)
181DEFINE_SIMPLE_ALIAS(Floor, std::floor)
182DEFINE_SIMPLE_ALIAS(Fma, std::fma)
183DEFINE_SIMPLE_ALIAS(Frexp, std::frexp)
184DEFINE_SIMPLE_ALIAS(Hypot, std::hypot)
185DEFINE_SIMPLE_ALIAS(Ilogb, std::ilogb)
186DEFINE_SIMPLE_ALIAS(Isinf, std::isinf)
187DEFINE_SIMPLE_ALIAS(Isnan, std::isnan)
188DEFINE_SIMPLE_ALIAS(J0, j0l)
189DEFINE_SIMPLE_ALIAS(J1, j1l)
190DEFINE_SIMPLE_ALIAS(Jn, jnl)
191DEFINE_SIMPLE_ALIAS(Ldexp, std::ldexp)
192DEFINE_SIMPLE_ALIAS(Lgamma, std::lgamma)
193DEFINE_SIMPLE_ALIAS(Llround, std::llround)
194DEFINE_SIMPLE_ALIAS(Log, std::log)
195DEFINE_SIMPLE_ALIAS(Log10, std::log10)
196DEFINE_SIMPLE_ALIAS(Lround, std::lround)
197DEFINE_SIMPLE_ALIAS(Nextafter, std::nextafter)
198DEFINE_SIMPLE_ALIAS(Pow, std::pow)
199DEFINE_SIMPLE_ALIAS(Round, std::round)
200DEFINE_SIMPLE_ALIAS(Sin, std::sin)
201DEFINE_SIMPLE_ALIAS(Sinh, std::sinh)
202DEFINE_SIMPLE_ALIAS(Sqrt, std::sqrt)
203DEFINE_SIMPLE_ALIAS(Tan, std::tan)
204DEFINE_SIMPLE_ALIAS(Tanh, std::tanh)
205DEFINE_SIMPLE_ALIAS(Tgamma, std::tgamma)
206DEFINE_SIMPLE_ALIAS(Trunc, std::trunc)
207DEFINE_SIMPLE_ALIAS(Y0, y0l)
208DEFINE_SIMPLE_ALIAS(Y1, y1l)
209DEFINE_SIMPLE_ALIAS(Yn, ynl)
210
211// Use numeric_limits to produce infinity of the right type.
212#define F128_RT_INFINITY \
213 (std::numeric_limits<CppTypeFor<TypeCategory::Real, 16>>::infinity())
214#define F128_RT_QNAN \
215 (std::numeric_limits<CppTypeFor<TypeCategory::Real, 16>>::quiet_NaN())
216#elif HAS_LIBMF128
217// We can use __float128 versions of libm functions.
218// __STDC_WANT_IEC_60559_TYPES_EXT__ needs to be defined
219// before including cmath to enable the *f128 prototypes.
220#error "Float128Math build with glibc>=2.26 is unsupported yet"
221#endif
222
223} // namespace Fortran::runtime
224
225#endif // FORTRAN_RUNTIME_FLOAT128MATH_MATH_ENTRIES_H_
226

source code of flang/runtime/Float128Math/math-entries.h