1*412f47f9SXin Li /*
2*412f47f9SXin Li * Configuration for math routines.
3*412f47f9SXin Li *
4*412f47f9SXin Li * Copyright (c) 2017-2023, Arm Limited.
5*412f47f9SXin Li * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
6*412f47f9SXin Li */
7*412f47f9SXin Li
8*412f47f9SXin Li #ifndef _MATH_CONFIG_H
9*412f47f9SXin Li #define _MATH_CONFIG_H
10*412f47f9SXin Li
11*412f47f9SXin Li #include <math.h>
12*412f47f9SXin Li #include <stdint.h>
13*412f47f9SXin Li
14*412f47f9SXin Li #ifndef WANT_ROUNDING
15*412f47f9SXin Li /* If defined to 1, return correct results for special cases in non-nearest
16*412f47f9SXin Li rounding modes (logf (1.0f) returns 0.0f with FE_DOWNWARD rather than -0.0f).
17*412f47f9SXin Li This may be set to 0 if there is no fenv support or if math functions only
18*412f47f9SXin Li get called in round to nearest mode. */
19*412f47f9SXin Li # define WANT_ROUNDING 1
20*412f47f9SXin Li #endif
21*412f47f9SXin Li #ifndef WANT_ERRNO
22*412f47f9SXin Li /* If defined to 1, set errno in math functions according to ISO C. Many math
23*412f47f9SXin Li libraries do not set errno, so this is 0 by default. It may need to be
24*412f47f9SXin Li set to 1 if math.h has (math_errhandling & MATH_ERRNO) != 0. */
25*412f47f9SXin Li # define WANT_ERRNO 0
26*412f47f9SXin Li #endif
27*412f47f9SXin Li #ifndef WANT_ERRNO_UFLOW
28*412f47f9SXin Li /* Set errno to ERANGE if result underflows to 0 (in all rounding modes). */
29*412f47f9SXin Li # define WANT_ERRNO_UFLOW (WANT_ROUNDING && WANT_ERRNO)
30*412f47f9SXin Li #endif
31*412f47f9SXin Li
32*412f47f9SXin Li /* Compiler can inline round as a single instruction. */
33*412f47f9SXin Li #ifndef HAVE_FAST_ROUND
34*412f47f9SXin Li # if __aarch64__
35*412f47f9SXin Li # define HAVE_FAST_ROUND 1
36*412f47f9SXin Li # else
37*412f47f9SXin Li # define HAVE_FAST_ROUND 0
38*412f47f9SXin Li # endif
39*412f47f9SXin Li #endif
40*412f47f9SXin Li
41*412f47f9SXin Li /* Compiler can inline lround, but not (long)round(x). */
42*412f47f9SXin Li #ifndef HAVE_FAST_LROUND
43*412f47f9SXin Li # if __aarch64__ && (100*__GNUC__ + __GNUC_MINOR__) >= 408 && __NO_MATH_ERRNO__
44*412f47f9SXin Li # define HAVE_FAST_LROUND 1
45*412f47f9SXin Li # else
46*412f47f9SXin Li # define HAVE_FAST_LROUND 0
47*412f47f9SXin Li # endif
48*412f47f9SXin Li #endif
49*412f47f9SXin Li
50*412f47f9SXin Li /* Compiler can inline fma as a single instruction. */
51*412f47f9SXin Li #ifndef HAVE_FAST_FMA
52*412f47f9SXin Li # if defined FP_FAST_FMA || __aarch64__
53*412f47f9SXin Li # define HAVE_FAST_FMA 1
54*412f47f9SXin Li # else
55*412f47f9SXin Li # define HAVE_FAST_FMA 0
56*412f47f9SXin Li # endif
57*412f47f9SXin Li #endif
58*412f47f9SXin Li
59*412f47f9SXin Li /* Provide *_finite symbols and some of the glibc hidden symbols
60*412f47f9SXin Li so libmathlib can be used with binaries compiled against glibc
61*412f47f9SXin Li to interpose math functions with both static and dynamic linking. */
62*412f47f9SXin Li #ifndef USE_GLIBC_ABI
63*412f47f9SXin Li # if __GNUC__
64*412f47f9SXin Li # define USE_GLIBC_ABI 1
65*412f47f9SXin Li # else
66*412f47f9SXin Li # define USE_GLIBC_ABI 0
67*412f47f9SXin Li # endif
68*412f47f9SXin Li #endif
69*412f47f9SXin Li
70*412f47f9SXin Li /* Optionally used extensions. */
71*412f47f9SXin Li #ifdef __GNUC__
72*412f47f9SXin Li # define HIDDEN __attribute__ ((__visibility__ ("hidden")))
73*412f47f9SXin Li # define NOINLINE __attribute__ ((noinline))
74*412f47f9SXin Li # define UNUSED __attribute__ ((unused))
75*412f47f9SXin Li # define likely(x) __builtin_expect (!!(x), 1)
76*412f47f9SXin Li # define unlikely(x) __builtin_expect (x, 0)
77*412f47f9SXin Li # if __GNUC__ >= 9
78*412f47f9SXin Li # define attribute_copy(f) __attribute__ ((copy (f)))
79*412f47f9SXin Li # else
80*412f47f9SXin Li # define attribute_copy(f)
81*412f47f9SXin Li # endif
82*412f47f9SXin Li # define strong_alias(f, a) \
83*412f47f9SXin Li extern __typeof (f) a __attribute__ ((alias (#f))) attribute_copy (f);
84*412f47f9SXin Li # define hidden_alias(f, a) \
85*412f47f9SXin Li extern __typeof (f) a __attribute__ ((alias (#f), visibility ("hidden"))) \
86*412f47f9SXin Li attribute_copy (f);
87*412f47f9SXin Li #else
88*412f47f9SXin Li # define HIDDEN
89*412f47f9SXin Li # define NOINLINE
90*412f47f9SXin Li # define UNUSED
91*412f47f9SXin Li # define likely(x) (x)
92*412f47f9SXin Li # define unlikely(x) (x)
93*412f47f9SXin Li #endif
94*412f47f9SXin Li
95*412f47f9SXin Li /* Return ptr but hide its value from the compiler so accesses through it
96*412f47f9SXin Li cannot be optimized based on the contents. */
97*412f47f9SXin Li #define ptr_barrier(ptr) \
98*412f47f9SXin Li ({ \
99*412f47f9SXin Li __typeof (ptr) __ptr = (ptr); \
100*412f47f9SXin Li __asm("" : "+r"(__ptr)); \
101*412f47f9SXin Li __ptr; \
102*412f47f9SXin Li })
103*412f47f9SXin Li
104*412f47f9SXin Li /* Symbol renames to avoid libc conflicts. */
105*412f47f9SXin Li #define __math_oflowf arm_math_oflowf
106*412f47f9SXin Li #define __math_uflowf arm_math_uflowf
107*412f47f9SXin Li #define __math_may_uflowf arm_math_may_uflowf
108*412f47f9SXin Li #define __math_divzerof arm_math_divzerof
109*412f47f9SXin Li #define __math_oflow arm_math_oflow
110*412f47f9SXin Li #define __math_uflow arm_math_uflow
111*412f47f9SXin Li #define __math_may_uflow arm_math_may_uflow
112*412f47f9SXin Li #define __math_divzero arm_math_divzero
113*412f47f9SXin Li #define __math_invalidf arm_math_invalidf
114*412f47f9SXin Li #define __math_invalid arm_math_invalid
115*412f47f9SXin Li #define __math_check_oflow arm_math_check_oflow
116*412f47f9SXin Li #define __math_check_uflow arm_math_check_uflow
117*412f47f9SXin Li #define __math_check_oflowf arm_math_check_oflowf
118*412f47f9SXin Li #define __math_check_uflowf arm_math_check_uflowf
119*412f47f9SXin Li
120*412f47f9SXin Li #define __sincosf_table arm_math_sincosf_table
121*412f47f9SXin Li #define __inv_pio4 arm_math_inv_pio4
122*412f47f9SXin Li #define __exp2f_data arm_math_exp2f_data
123*412f47f9SXin Li #define __logf_data arm_math_logf_data
124*412f47f9SXin Li #define __log2f_data arm_math_log2f_data
125*412f47f9SXin Li #define __powf_log2_data arm_math_powf_log2_data
126*412f47f9SXin Li #define __exp_data arm_math_exp_data
127*412f47f9SXin Li #define __log_data arm_math_log_data
128*412f47f9SXin Li #define __log2_data arm_math_log2_data
129*412f47f9SXin Li #define __pow_log_data arm_math_pow_log_data
130*412f47f9SXin Li #define __erff_data arm_math_erff_data
131*412f47f9SXin Li #define __erf_data arm_math_erf_data
132*412f47f9SXin Li #define __v_exp_data arm_math_v_exp_data
133*412f47f9SXin Li #define __v_log_data arm_math_v_log_data
134*412f47f9SXin Li
135*412f47f9SXin Li #if HAVE_FAST_ROUND
136*412f47f9SXin Li /* When set, the roundtoint and converttoint functions are provided with
137*412f47f9SXin Li the semantics documented below. */
138*412f47f9SXin Li # define TOINT_INTRINSICS 1
139*412f47f9SXin Li
140*412f47f9SXin Li /* Round x to nearest int in all rounding modes, ties have to be rounded
141*412f47f9SXin Li consistently with converttoint so the results match. If the result
142*412f47f9SXin Li would be outside of [-2^31, 2^31-1] then the semantics is unspecified. */
143*412f47f9SXin Li static inline double_t
roundtoint(double_t x)144*412f47f9SXin Li roundtoint (double_t x)
145*412f47f9SXin Li {
146*412f47f9SXin Li return round (x);
147*412f47f9SXin Li }
148*412f47f9SXin Li
149*412f47f9SXin Li /* Convert x to nearest int in all rounding modes, ties have to be rounded
150*412f47f9SXin Li consistently with roundtoint. If the result is not representible in an
151*412f47f9SXin Li int32_t then the semantics is unspecified. */
152*412f47f9SXin Li static inline int32_t
converttoint(double_t x)153*412f47f9SXin Li converttoint (double_t x)
154*412f47f9SXin Li {
155*412f47f9SXin Li # if HAVE_FAST_LROUND
156*412f47f9SXin Li return lround (x);
157*412f47f9SXin Li # else
158*412f47f9SXin Li return (long) round (x);
159*412f47f9SXin Li # endif
160*412f47f9SXin Li }
161*412f47f9SXin Li #endif
162*412f47f9SXin Li
163*412f47f9SXin Li static inline uint32_t
asuint(float f)164*412f47f9SXin Li asuint (float f)
165*412f47f9SXin Li {
166*412f47f9SXin Li union
167*412f47f9SXin Li {
168*412f47f9SXin Li float f;
169*412f47f9SXin Li uint32_t i;
170*412f47f9SXin Li } u = {f};
171*412f47f9SXin Li return u.i;
172*412f47f9SXin Li }
173*412f47f9SXin Li
174*412f47f9SXin Li static inline float
asfloat(uint32_t i)175*412f47f9SXin Li asfloat (uint32_t i)
176*412f47f9SXin Li {
177*412f47f9SXin Li union
178*412f47f9SXin Li {
179*412f47f9SXin Li uint32_t i;
180*412f47f9SXin Li float f;
181*412f47f9SXin Li } u = {i};
182*412f47f9SXin Li return u.f;
183*412f47f9SXin Li }
184*412f47f9SXin Li
185*412f47f9SXin Li static inline uint64_t
asuint64(double f)186*412f47f9SXin Li asuint64 (double f)
187*412f47f9SXin Li {
188*412f47f9SXin Li union
189*412f47f9SXin Li {
190*412f47f9SXin Li double f;
191*412f47f9SXin Li uint64_t i;
192*412f47f9SXin Li } u = {f};
193*412f47f9SXin Li return u.i;
194*412f47f9SXin Li }
195*412f47f9SXin Li
196*412f47f9SXin Li static inline double
asdouble(uint64_t i)197*412f47f9SXin Li asdouble (uint64_t i)
198*412f47f9SXin Li {
199*412f47f9SXin Li union
200*412f47f9SXin Li {
201*412f47f9SXin Li uint64_t i;
202*412f47f9SXin Li double f;
203*412f47f9SXin Li } u = {i};
204*412f47f9SXin Li return u.f;
205*412f47f9SXin Li }
206*412f47f9SXin Li
207*412f47f9SXin Li #ifndef IEEE_754_2008_SNAN
208*412f47f9SXin Li # define IEEE_754_2008_SNAN 1
209*412f47f9SXin Li #endif
210*412f47f9SXin Li static inline int
issignalingf_inline(float x)211*412f47f9SXin Li issignalingf_inline (float x)
212*412f47f9SXin Li {
213*412f47f9SXin Li uint32_t ix = asuint (x);
214*412f47f9SXin Li if (!IEEE_754_2008_SNAN)
215*412f47f9SXin Li return (ix & 0x7fc00000) == 0x7fc00000;
216*412f47f9SXin Li return 2 * (ix ^ 0x00400000) > 2u * 0x7fc00000;
217*412f47f9SXin Li }
218*412f47f9SXin Li
219*412f47f9SXin Li static inline int
issignaling_inline(double x)220*412f47f9SXin Li issignaling_inline (double x)
221*412f47f9SXin Li {
222*412f47f9SXin Li uint64_t ix = asuint64 (x);
223*412f47f9SXin Li if (!IEEE_754_2008_SNAN)
224*412f47f9SXin Li return (ix & 0x7ff8000000000000) == 0x7ff8000000000000;
225*412f47f9SXin Li return 2 * (ix ^ 0x0008000000000000) > 2 * 0x7ff8000000000000ULL;
226*412f47f9SXin Li }
227*412f47f9SXin Li
228*412f47f9SXin Li #if __aarch64__ && __GNUC__
229*412f47f9SXin Li /* Prevent the optimization of a floating-point expression. */
230*412f47f9SXin Li static inline float
opt_barrier_float(float x)231*412f47f9SXin Li opt_barrier_float (float x)
232*412f47f9SXin Li {
233*412f47f9SXin Li __asm__ __volatile__ ("" : "+w" (x));
234*412f47f9SXin Li return x;
235*412f47f9SXin Li }
236*412f47f9SXin Li static inline double
opt_barrier_double(double x)237*412f47f9SXin Li opt_barrier_double (double x)
238*412f47f9SXin Li {
239*412f47f9SXin Li __asm__ __volatile__ ("" : "+w" (x));
240*412f47f9SXin Li return x;
241*412f47f9SXin Li }
242*412f47f9SXin Li /* Force the evaluation of a floating-point expression for its side-effect. */
243*412f47f9SXin Li static inline void
force_eval_float(float x)244*412f47f9SXin Li force_eval_float (float x)
245*412f47f9SXin Li {
246*412f47f9SXin Li __asm__ __volatile__ ("" : "+w" (x));
247*412f47f9SXin Li }
248*412f47f9SXin Li static inline void
force_eval_double(double x)249*412f47f9SXin Li force_eval_double (double x)
250*412f47f9SXin Li {
251*412f47f9SXin Li __asm__ __volatile__ ("" : "+w" (x));
252*412f47f9SXin Li }
253*412f47f9SXin Li #else
254*412f47f9SXin Li static inline float
opt_barrier_float(float x)255*412f47f9SXin Li opt_barrier_float (float x)
256*412f47f9SXin Li {
257*412f47f9SXin Li volatile float y = x;
258*412f47f9SXin Li return y;
259*412f47f9SXin Li }
260*412f47f9SXin Li static inline double
opt_barrier_double(double x)261*412f47f9SXin Li opt_barrier_double (double x)
262*412f47f9SXin Li {
263*412f47f9SXin Li volatile double y = x;
264*412f47f9SXin Li return y;
265*412f47f9SXin Li }
266*412f47f9SXin Li static inline void
force_eval_float(float x)267*412f47f9SXin Li force_eval_float (float x)
268*412f47f9SXin Li {
269*412f47f9SXin Li volatile float y UNUSED = x;
270*412f47f9SXin Li }
271*412f47f9SXin Li static inline void
force_eval_double(double x)272*412f47f9SXin Li force_eval_double (double x)
273*412f47f9SXin Li {
274*412f47f9SXin Li volatile double y UNUSED = x;
275*412f47f9SXin Li }
276*412f47f9SXin Li #endif
277*412f47f9SXin Li
278*412f47f9SXin Li /* Evaluate an expression as the specified type, normally a type
279*412f47f9SXin Li cast should be enough, but compilers implement non-standard
280*412f47f9SXin Li excess-precision handling, so when FLT_EVAL_METHOD != 0 then
281*412f47f9SXin Li these functions may need to be customized. */
282*412f47f9SXin Li static inline float
eval_as_float(float x)283*412f47f9SXin Li eval_as_float (float x)
284*412f47f9SXin Li {
285*412f47f9SXin Li return x;
286*412f47f9SXin Li }
287*412f47f9SXin Li static inline double
eval_as_double(double x)288*412f47f9SXin Li eval_as_double (double x)
289*412f47f9SXin Li {
290*412f47f9SXin Li return x;
291*412f47f9SXin Li }
292*412f47f9SXin Li
293*412f47f9SXin Li /* Error handling tail calls for special cases, with a sign argument.
294*412f47f9SXin Li The sign of the return value is set if the argument is non-zero. */
295*412f47f9SXin Li
296*412f47f9SXin Li /* The result overflows. */
297*412f47f9SXin Li HIDDEN float __math_oflowf (uint32_t);
298*412f47f9SXin Li /* The result underflows to 0 in nearest rounding mode. */
299*412f47f9SXin Li HIDDEN float __math_uflowf (uint32_t);
300*412f47f9SXin Li /* The result underflows to 0 in some directed rounding mode only. */
301*412f47f9SXin Li HIDDEN float __math_may_uflowf (uint32_t);
302*412f47f9SXin Li /* Division by zero. */
303*412f47f9SXin Li HIDDEN float __math_divzerof (uint32_t);
304*412f47f9SXin Li /* The result overflows. */
305*412f47f9SXin Li HIDDEN double __math_oflow (uint32_t);
306*412f47f9SXin Li /* The result underflows to 0 in nearest rounding mode. */
307*412f47f9SXin Li HIDDEN double __math_uflow (uint32_t);
308*412f47f9SXin Li /* The result underflows to 0 in some directed rounding mode only. */
309*412f47f9SXin Li HIDDEN double __math_may_uflow (uint32_t);
310*412f47f9SXin Li /* Division by zero. */
311*412f47f9SXin Li HIDDEN double __math_divzero (uint32_t);
312*412f47f9SXin Li
313*412f47f9SXin Li /* Error handling using input checking. */
314*412f47f9SXin Li
315*412f47f9SXin Li /* Invalid input unless it is a quiet NaN. */
316*412f47f9SXin Li HIDDEN float __math_invalidf (float);
317*412f47f9SXin Li /* Invalid input unless it is a quiet NaN. */
318*412f47f9SXin Li HIDDEN double __math_invalid (double);
319*412f47f9SXin Li
320*412f47f9SXin Li /* Error handling using output checking, only for errno setting. */
321*412f47f9SXin Li
322*412f47f9SXin Li /* Check if the result overflowed to infinity. */
323*412f47f9SXin Li HIDDEN double __math_check_oflow (double);
324*412f47f9SXin Li /* Check if the result underflowed to 0. */
325*412f47f9SXin Li HIDDEN double __math_check_uflow (double);
326*412f47f9SXin Li
327*412f47f9SXin Li /* Check if the result overflowed to infinity. */
328*412f47f9SXin Li static inline double
check_oflow(double x)329*412f47f9SXin Li check_oflow (double x)
330*412f47f9SXin Li {
331*412f47f9SXin Li return WANT_ERRNO ? __math_check_oflow (x) : x;
332*412f47f9SXin Li }
333*412f47f9SXin Li
334*412f47f9SXin Li /* Check if the result underflowed to 0. */
335*412f47f9SXin Li static inline double
check_uflow(double x)336*412f47f9SXin Li check_uflow (double x)
337*412f47f9SXin Li {
338*412f47f9SXin Li return WANT_ERRNO ? __math_check_uflow (x) : x;
339*412f47f9SXin Li }
340*412f47f9SXin Li
341*412f47f9SXin Li /* Check if the result overflowed to infinity. */
342*412f47f9SXin Li HIDDEN float __math_check_oflowf (float);
343*412f47f9SXin Li /* Check if the result underflowed to 0. */
344*412f47f9SXin Li HIDDEN float __math_check_uflowf (float);
345*412f47f9SXin Li
346*412f47f9SXin Li /* Check if the result overflowed to infinity. */
347*412f47f9SXin Li static inline float
check_oflowf(float x)348*412f47f9SXin Li check_oflowf (float x)
349*412f47f9SXin Li {
350*412f47f9SXin Li return WANT_ERRNO ? __math_check_oflowf (x) : x;
351*412f47f9SXin Li }
352*412f47f9SXin Li
353*412f47f9SXin Li /* Check if the result underflowed to 0. */
354*412f47f9SXin Li static inline float
check_uflowf(float x)355*412f47f9SXin Li check_uflowf (float x)
356*412f47f9SXin Li {
357*412f47f9SXin Li return WANT_ERRNO ? __math_check_uflowf (x) : x;
358*412f47f9SXin Li }
359*412f47f9SXin Li
360*412f47f9SXin Li /* Shared between expf, exp2f and powf. */
361*412f47f9SXin Li #define EXP2F_TABLE_BITS 5
362*412f47f9SXin Li #define EXP2F_POLY_ORDER 3
363*412f47f9SXin Li extern const struct exp2f_data
364*412f47f9SXin Li {
365*412f47f9SXin Li uint64_t tab[1 << EXP2F_TABLE_BITS];
366*412f47f9SXin Li double shift_scaled;
367*412f47f9SXin Li double poly[EXP2F_POLY_ORDER];
368*412f47f9SXin Li double shift;
369*412f47f9SXin Li double invln2_scaled;
370*412f47f9SXin Li double poly_scaled[EXP2F_POLY_ORDER];
371*412f47f9SXin Li } __exp2f_data HIDDEN;
372*412f47f9SXin Li
373*412f47f9SXin Li #define LOGF_TABLE_BITS 4
374*412f47f9SXin Li #define LOGF_POLY_ORDER 4
375*412f47f9SXin Li extern const struct logf_data
376*412f47f9SXin Li {
377*412f47f9SXin Li struct
378*412f47f9SXin Li {
379*412f47f9SXin Li double invc, logc;
380*412f47f9SXin Li } tab[1 << LOGF_TABLE_BITS];
381*412f47f9SXin Li double ln2;
382*412f47f9SXin Li double poly[LOGF_POLY_ORDER - 1]; /* First order coefficient is 1. */
383*412f47f9SXin Li } __logf_data HIDDEN;
384*412f47f9SXin Li
385*412f47f9SXin Li #define LOG2F_TABLE_BITS 4
386*412f47f9SXin Li #define LOG2F_POLY_ORDER 4
387*412f47f9SXin Li extern const struct log2f_data
388*412f47f9SXin Li {
389*412f47f9SXin Li struct
390*412f47f9SXin Li {
391*412f47f9SXin Li double invc, logc;
392*412f47f9SXin Li } tab[1 << LOG2F_TABLE_BITS];
393*412f47f9SXin Li double poly[LOG2F_POLY_ORDER];
394*412f47f9SXin Li } __log2f_data HIDDEN;
395*412f47f9SXin Li
396*412f47f9SXin Li #define POWF_LOG2_TABLE_BITS 4
397*412f47f9SXin Li #define POWF_LOG2_POLY_ORDER 5
398*412f47f9SXin Li #if TOINT_INTRINSICS
399*412f47f9SXin Li # define POWF_SCALE_BITS EXP2F_TABLE_BITS
400*412f47f9SXin Li #else
401*412f47f9SXin Li # define POWF_SCALE_BITS 0
402*412f47f9SXin Li #endif
403*412f47f9SXin Li #define POWF_SCALE ((double) (1 << POWF_SCALE_BITS))
404*412f47f9SXin Li extern const struct powf_log2_data
405*412f47f9SXin Li {
406*412f47f9SXin Li struct
407*412f47f9SXin Li {
408*412f47f9SXin Li double invc, logc;
409*412f47f9SXin Li } tab[1 << POWF_LOG2_TABLE_BITS];
410*412f47f9SXin Li double poly[POWF_LOG2_POLY_ORDER];
411*412f47f9SXin Li } __powf_log2_data HIDDEN;
412*412f47f9SXin Li
413*412f47f9SXin Li
414*412f47f9SXin Li #define EXP_TABLE_BITS 7
415*412f47f9SXin Li #define EXP_POLY_ORDER 5
416*412f47f9SXin Li /* Use polynomial that is optimized for a wider input range. This may be
417*412f47f9SXin Li needed for good precision in non-nearest rounding and !TOINT_INTRINSICS. */
418*412f47f9SXin Li #define EXP_POLY_WIDE 0
419*412f47f9SXin Li /* Use close to nearest rounding toint when !TOINT_INTRINSICS. This may be
420*412f47f9SXin Li needed for good precision in non-nearest rouning and !EXP_POLY_WIDE. */
421*412f47f9SXin Li #define EXP_USE_TOINT_NARROW 0
422*412f47f9SXin Li #define EXP2_POLY_ORDER 5
423*412f47f9SXin Li #define EXP2_POLY_WIDE 0
424*412f47f9SXin Li /* Wider exp10 polynomial necessary for good precision in non-nearest rounding
425*412f47f9SXin Li and !TOINT_INTRINSICS. */
426*412f47f9SXin Li #define EXP10_POLY_WIDE 0
427*412f47f9SXin Li extern const struct exp_data
428*412f47f9SXin Li {
429*412f47f9SXin Li double invln2N;
430*412f47f9SXin Li double invlog10_2N;
431*412f47f9SXin Li double shift;
432*412f47f9SXin Li double negln2hiN;
433*412f47f9SXin Li double negln2loN;
434*412f47f9SXin Li double neglog10_2hiN;
435*412f47f9SXin Li double neglog10_2loN;
436*412f47f9SXin Li double poly[4]; /* Last four coefficients. */
437*412f47f9SXin Li double exp2_shift;
438*412f47f9SXin Li double exp2_poly[EXP2_POLY_ORDER];
439*412f47f9SXin Li double exp10_poly[5];
440*412f47f9SXin Li uint64_t tab[2*(1 << EXP_TABLE_BITS)];
441*412f47f9SXin Li } __exp_data HIDDEN;
442*412f47f9SXin Li
443*412f47f9SXin Li #define LOG_TABLE_BITS 7
444*412f47f9SXin Li #define LOG_POLY_ORDER 6
445*412f47f9SXin Li #define LOG_POLY1_ORDER 12
446*412f47f9SXin Li extern const struct log_data
447*412f47f9SXin Li {
448*412f47f9SXin Li double ln2hi;
449*412f47f9SXin Li double ln2lo;
450*412f47f9SXin Li double poly[LOG_POLY_ORDER - 1]; /* First coefficient is 1. */
451*412f47f9SXin Li double poly1[LOG_POLY1_ORDER - 1];
452*412f47f9SXin Li struct {double invc, logc;} tab[1 << LOG_TABLE_BITS];
453*412f47f9SXin Li #if !HAVE_FAST_FMA
454*412f47f9SXin Li struct {double chi, clo;} tab2[1 << LOG_TABLE_BITS];
455*412f47f9SXin Li #endif
456*412f47f9SXin Li } __log_data HIDDEN;
457*412f47f9SXin Li
458*412f47f9SXin Li #define LOG2_TABLE_BITS 6
459*412f47f9SXin Li #define LOG2_POLY_ORDER 7
460*412f47f9SXin Li #define LOG2_POLY1_ORDER 11
461*412f47f9SXin Li extern const struct log2_data
462*412f47f9SXin Li {
463*412f47f9SXin Li double invln2hi;
464*412f47f9SXin Li double invln2lo;
465*412f47f9SXin Li double poly[LOG2_POLY_ORDER - 1];
466*412f47f9SXin Li double poly1[LOG2_POLY1_ORDER - 1];
467*412f47f9SXin Li struct {double invc, logc;} tab[1 << LOG2_TABLE_BITS];
468*412f47f9SXin Li #if !HAVE_FAST_FMA
469*412f47f9SXin Li struct {double chi, clo;} tab2[1 << LOG2_TABLE_BITS];
470*412f47f9SXin Li #endif
471*412f47f9SXin Li } __log2_data HIDDEN;
472*412f47f9SXin Li
473*412f47f9SXin Li #define POW_LOG_TABLE_BITS 7
474*412f47f9SXin Li #define POW_LOG_POLY_ORDER 8
475*412f47f9SXin Li extern const struct pow_log_data
476*412f47f9SXin Li {
477*412f47f9SXin Li double ln2hi;
478*412f47f9SXin Li double ln2lo;
479*412f47f9SXin Li double poly[POW_LOG_POLY_ORDER - 1]; /* First coefficient is 1. */
480*412f47f9SXin Li /* Note: the pad field is unused, but allows slightly faster indexing. */
481*412f47f9SXin Li struct {double invc, pad, logc, logctail;} tab[1 << POW_LOG_TABLE_BITS];
482*412f47f9SXin Li } __pow_log_data HIDDEN;
483*412f47f9SXin Li
484*412f47f9SXin Li extern const struct erff_data
485*412f47f9SXin Li {
486*412f47f9SXin Li float erff_poly_A[6];
487*412f47f9SXin Li float erff_poly_B[7];
488*412f47f9SXin Li } __erff_data HIDDEN;
489*412f47f9SXin Li
490*412f47f9SXin Li #define ERF_POLY_A_ORDER 19
491*412f47f9SXin Li #define ERF_POLY_A_NCOEFFS 10
492*412f47f9SXin Li #define ERFC_POLY_C_NCOEFFS 16
493*412f47f9SXin Li #define ERFC_POLY_D_NCOEFFS 18
494*412f47f9SXin Li #define ERFC_POLY_E_NCOEFFS 14
495*412f47f9SXin Li #define ERFC_POLY_F_NCOEFFS 17
496*412f47f9SXin Li extern const struct erf_data
497*412f47f9SXin Li {
498*412f47f9SXin Li double erf_poly_A[ERF_POLY_A_NCOEFFS];
499*412f47f9SXin Li double erf_ratio_N_A[5];
500*412f47f9SXin Li double erf_ratio_D_A[5];
501*412f47f9SXin Li double erf_ratio_N_B[7];
502*412f47f9SXin Li double erf_ratio_D_B[6];
503*412f47f9SXin Li double erfc_poly_C[ERFC_POLY_C_NCOEFFS];
504*412f47f9SXin Li double erfc_poly_D[ERFC_POLY_D_NCOEFFS];
505*412f47f9SXin Li double erfc_poly_E[ERFC_POLY_E_NCOEFFS];
506*412f47f9SXin Li double erfc_poly_F[ERFC_POLY_F_NCOEFFS];
507*412f47f9SXin Li } __erf_data HIDDEN;
508*412f47f9SXin Li
509*412f47f9SXin Li #define V_EXP_TABLE_BITS 7
510*412f47f9SXin Li extern const uint64_t __v_exp_data[1 << V_EXP_TABLE_BITS] HIDDEN;
511*412f47f9SXin Li
512*412f47f9SXin Li #define V_LOG_TABLE_BITS 7
513*412f47f9SXin Li extern const struct v_log_data
514*412f47f9SXin Li {
515*412f47f9SXin Li struct
516*412f47f9SXin Li {
517*412f47f9SXin Li double invc, logc;
518*412f47f9SXin Li } table[1 << V_LOG_TABLE_BITS];
519*412f47f9SXin Li } __v_log_data HIDDEN;
520*412f47f9SXin Li
521*412f47f9SXin Li #endif
522