xref: /aosp_15_r20/external/arm-optimized-routines/math/math_config.h (revision 412f47f9e737e10ed5cc46ec6a8d7fa2264f8a14)
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