xref: /freebsd-src/contrib/arm-optimized-routines/math/math_config.h (revision f3087bef11543b42e0d69b708f367097a4118d24)
131914882SAlex Richardson /*
231914882SAlex Richardson  * Configuration for math routines.
331914882SAlex Richardson  *
4*f3087befSAndrew Turner  * Copyright (c) 2017-2024, Arm Limited.
5072a4ba8SAndrew Turner  * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
631914882SAlex Richardson  */
731914882SAlex Richardson 
831914882SAlex Richardson #ifndef _MATH_CONFIG_H
931914882SAlex Richardson #define _MATH_CONFIG_H
1031914882SAlex Richardson 
1131914882SAlex Richardson #include <math.h>
1231914882SAlex Richardson #include <stdint.h>
1331914882SAlex Richardson 
1431914882SAlex Richardson #ifndef WANT_ROUNDING
1531914882SAlex Richardson /* If defined to 1, return correct results for special cases in non-nearest
16*f3087befSAndrew Turner    rounding modes (logf (1.0f) returns 0.0f with FE_DOWNWARD rather than
17*f3087befSAndrew Turner    -0.0f). This may be set to 0 if there is no fenv support or if math
18*f3087befSAndrew Turner    functions only get called in round to nearest mode.  */
1931914882SAlex Richardson # define WANT_ROUNDING 1
2031914882SAlex Richardson #endif
2131914882SAlex Richardson #ifndef WANT_ERRNO
2231914882SAlex Richardson /* If defined to 1, set errno in math functions according to ISO C.  Many math
2331914882SAlex Richardson    libraries do not set errno, so this is 0 by default.  It may need to be
2431914882SAlex Richardson    set to 1 if math.h has (math_errhandling & MATH_ERRNO) != 0.  */
2531914882SAlex Richardson # define WANT_ERRNO 0
2631914882SAlex Richardson #endif
2731914882SAlex Richardson #ifndef WANT_ERRNO_UFLOW
2831914882SAlex Richardson /* Set errno to ERANGE if result underflows to 0 (in all rounding modes).  */
2931914882SAlex Richardson # define WANT_ERRNO_UFLOW (WANT_ROUNDING && WANT_ERRNO)
3031914882SAlex Richardson #endif
3131914882SAlex Richardson 
3231914882SAlex Richardson /* Compiler can inline round as a single instruction.  */
3331914882SAlex Richardson #ifndef HAVE_FAST_ROUND
3431914882SAlex Richardson # if __aarch64__
3531914882SAlex Richardson #   define HAVE_FAST_ROUND 1
3631914882SAlex Richardson # else
3731914882SAlex Richardson #   define HAVE_FAST_ROUND 0
3831914882SAlex Richardson # endif
3931914882SAlex Richardson #endif
4031914882SAlex Richardson 
4131914882SAlex Richardson /* Compiler can inline lround, but not (long)round(x).  */
4231914882SAlex Richardson #ifndef HAVE_FAST_LROUND
4331914882SAlex Richardson # if __aarch64__ && (100*__GNUC__ + __GNUC_MINOR__) >= 408 && __NO_MATH_ERRNO__
4431914882SAlex Richardson #   define HAVE_FAST_LROUND 1
4531914882SAlex Richardson # else
4631914882SAlex Richardson #   define HAVE_FAST_LROUND 0
4731914882SAlex Richardson # endif
4831914882SAlex Richardson #endif
4931914882SAlex Richardson 
5031914882SAlex Richardson /* Compiler can inline fma as a single instruction.  */
5131914882SAlex Richardson #ifndef HAVE_FAST_FMA
5231914882SAlex Richardson # if defined FP_FAST_FMA || __aarch64__
5331914882SAlex Richardson #   define HAVE_FAST_FMA 1
5431914882SAlex Richardson # else
5531914882SAlex Richardson #   define HAVE_FAST_FMA 0
5631914882SAlex Richardson # endif
5731914882SAlex Richardson #endif
5831914882SAlex Richardson 
5931914882SAlex Richardson /* Provide *_finite symbols and some of the glibc hidden symbols
6031914882SAlex Richardson    so libmathlib can be used with binaries compiled against glibc
6131914882SAlex Richardson    to interpose math functions with both static and dynamic linking.  */
6231914882SAlex Richardson #ifndef USE_GLIBC_ABI
6331914882SAlex Richardson # if __GNUC__
6431914882SAlex Richardson #   define USE_GLIBC_ABI 1
6531914882SAlex Richardson # else
6631914882SAlex Richardson #   define USE_GLIBC_ABI 0
6731914882SAlex Richardson # endif
6831914882SAlex Richardson #endif
6931914882SAlex Richardson 
7031914882SAlex Richardson /* Optionally used extensions.  */
7131914882SAlex Richardson #ifdef __GNUC__
7231914882SAlex Richardson # define HIDDEN __attribute__ ((__visibility__ ("hidden")))
7331914882SAlex Richardson # define NOINLINE __attribute__ ((noinline))
7431914882SAlex Richardson # define UNUSED __attribute__ ((unused))
7531914882SAlex Richardson # define likely(x) __builtin_expect (!!(x), 1)
7631914882SAlex Richardson # define unlikely(x) __builtin_expect (x, 0)
7731914882SAlex Richardson # if __GNUC__ >= 9
7831914882SAlex Richardson #   define attribute_copy(f) __attribute__ ((copy (f)))
7931914882SAlex Richardson # else
8031914882SAlex Richardson #   define attribute_copy(f)
8131914882SAlex Richardson # endif
8231914882SAlex Richardson # define strong_alias(f, a) \
8331914882SAlex Richardson   extern __typeof (f) a __attribute__ ((alias (#f))) attribute_copy (f);
8431914882SAlex Richardson # define hidden_alias(f, a) \
8531914882SAlex Richardson   extern __typeof (f) a __attribute__ ((alias (#f), visibility ("hidden"))) \
8631914882SAlex Richardson   attribute_copy (f);
8731914882SAlex Richardson #else
8831914882SAlex Richardson # define HIDDEN
8931914882SAlex Richardson # define NOINLINE
9031914882SAlex Richardson # define UNUSED
9131914882SAlex Richardson # define likely(x) (x)
9231914882SAlex Richardson # define unlikely(x) (x)
9331914882SAlex Richardson #endif
9431914882SAlex Richardson 
955a02ffc3SAndrew Turner /* Return ptr but hide its value from the compiler so accesses through it
965a02ffc3SAndrew Turner    cannot be optimized based on the contents.  */
975a02ffc3SAndrew Turner #define ptr_barrier(ptr)                                                      \
985a02ffc3SAndrew Turner   ({                                                                          \
995a02ffc3SAndrew Turner     __typeof (ptr) __ptr = (ptr);                                             \
1005a02ffc3SAndrew Turner     __asm("" : "+r"(__ptr));                                                  \
1015a02ffc3SAndrew Turner     __ptr;                                                                    \
1025a02ffc3SAndrew Turner   })
1035a02ffc3SAndrew Turner 
1045a02ffc3SAndrew Turner /* Symbol renames to avoid libc conflicts.  */
1055a02ffc3SAndrew Turner #define __math_oflowf arm_math_oflowf
1065a02ffc3SAndrew Turner #define __math_uflowf arm_math_uflowf
1075a02ffc3SAndrew Turner #define __math_may_uflowf arm_math_may_uflowf
1085a02ffc3SAndrew Turner #define __math_divzerof arm_math_divzerof
1095a02ffc3SAndrew Turner #define __math_oflow arm_math_oflow
1105a02ffc3SAndrew Turner #define __math_uflow arm_math_uflow
1115a02ffc3SAndrew Turner #define __math_may_uflow arm_math_may_uflow
1125a02ffc3SAndrew Turner #define __math_divzero arm_math_divzero
1135a02ffc3SAndrew Turner #define __math_invalidf arm_math_invalidf
1145a02ffc3SAndrew Turner #define __math_invalid arm_math_invalid
1155a02ffc3SAndrew Turner #define __math_check_oflow arm_math_check_oflow
1165a02ffc3SAndrew Turner #define __math_check_uflow arm_math_check_uflow
1175a02ffc3SAndrew Turner #define __math_check_oflowf arm_math_check_oflowf
1185a02ffc3SAndrew Turner #define __math_check_uflowf arm_math_check_uflowf
1195a02ffc3SAndrew Turner 
120*f3087befSAndrew Turner #define __exp_data arm_math_exp_data
121*f3087befSAndrew Turner #define __asin_poly arm_math_asin_poly
122*f3087befSAndrew Turner #define __asinf_poly arm_math_asinf_poly
123*f3087befSAndrew Turner #define __asinh_data arm_math_asinh_data
124*f3087befSAndrew Turner #define __asinhf_data arm_math_asinhf_data
125*f3087befSAndrew Turner #define __atan_poly_data arm_math_atan_poly_data
126*f3087befSAndrew Turner #define __atanf_poly_data arm_math_atanf_poly_data
127*f3087befSAndrew Turner #define __cbrt_data arm_math_cbrt_data
128*f3087befSAndrew Turner #define __cbrtf_data arm_math_cbrtf_data
129*f3087befSAndrew Turner #define __erf_data arm_math_erf_data
130*f3087befSAndrew Turner #define __expf_data arm_math_expf_data
131*f3087befSAndrew Turner #define __expm1_poly arm_math_expm1_poly
132*f3087befSAndrew Turner #define __expm1f_poly arm_math_expm1f_poly
133*f3087befSAndrew Turner #define __log10_data arm_math_log10_data
134*f3087befSAndrew Turner #define __log1p_data arm_math_log1p_data
135*f3087befSAndrew Turner #define __log1pf_data arm_math_log1pf_data
136*f3087befSAndrew Turner #define __log_data arm_math_log_data
137*f3087befSAndrew Turner #define __tanf_poly_data arm_math_tanf_poly_data
138*f3087befSAndrew Turner #define __v_log_data arm_math_v_log_data
1395a02ffc3SAndrew Turner #define __sincosf_table arm_math_sincosf_table
1405a02ffc3SAndrew Turner #define __inv_pio4 arm_math_inv_pio4
1415a02ffc3SAndrew Turner #define __exp2f_data arm_math_exp2f_data
1425a02ffc3SAndrew Turner #define __logf_data arm_math_logf_data
1435a02ffc3SAndrew Turner #define __log2f_data arm_math_log2f_data
1445a02ffc3SAndrew Turner #define __powf_log2_data arm_math_powf_log2_data
1455a02ffc3SAndrew Turner #define __exp_data arm_math_exp_data
1465a02ffc3SAndrew Turner #define __log_data arm_math_log_data
1475a02ffc3SAndrew Turner #define __log2_data arm_math_log2_data
1485a02ffc3SAndrew Turner #define __pow_log_data arm_math_pow_log_data
1495a02ffc3SAndrew Turner #define __erff_data arm_math_erff_data
1505a02ffc3SAndrew Turner #define __erf_data arm_math_erf_data
1515a02ffc3SAndrew Turner #define __v_exp_data arm_math_v_exp_data
1525a02ffc3SAndrew Turner #define __v_log_data arm_math_v_log_data
153*f3087befSAndrew Turner #define __v_erf_data arm_math_v_erf_data
154*f3087befSAndrew Turner #define __v_erfc_data arm_math_v_erfc_data
155*f3087befSAndrew Turner #define __v_erfcf_data arm_math_v_erfcf_data
156*f3087befSAndrew Turner #define __v_erff_data arm_math_v_erff_data
157*f3087befSAndrew Turner #define __v_exp_tail_data arm_math_v_exp_tail_data
158*f3087befSAndrew Turner #define __v_log10_data arm_math_v_log10_data
159*f3087befSAndrew Turner #define __v_log2_data arm_math_v_log2_data
160*f3087befSAndrew Turner #define __v_pow_exp_data arm_math_v_pow_exp_data
161*f3087befSAndrew Turner #define __v_pow_log_data arm_math_v_pow_log_data
162*f3087befSAndrew Turner #define __v_powf_data arm_math_v_powf_data
163*f3087befSAndrew Turner 
164*f3087befSAndrew Turner /* On some platforms (in particular Windows) INFINITY and HUGE_VAL might
165*f3087befSAndrew Turner    be defined in such a way that might not produce the expected bit pattern,
166*f3087befSAndrew Turner    therefore we enforce the glibc math.h definition using a builtin that is
167*f3087befSAndrew Turner    supported in both gcc and clang.  */
168*f3087befSAndrew Turner #if defined (_WIN32) && (defined (__GNUC__) || defined (__clang__))
169*f3087befSAndrew Turner # undef INFINITY
170*f3087befSAndrew Turner # define INFINITY __builtin_inff()
171*f3087befSAndrew Turner #endif
1725a02ffc3SAndrew Turner 
17331914882SAlex Richardson #if HAVE_FAST_ROUND
17431914882SAlex Richardson /* When set, the roundtoint and converttoint functions are provided with
17531914882SAlex Richardson    the semantics documented below.  */
17631914882SAlex Richardson # define TOINT_INTRINSICS 1
17731914882SAlex Richardson 
17831914882SAlex Richardson /* Round x to nearest int in all rounding modes, ties have to be rounded
17931914882SAlex Richardson    consistently with converttoint so the results match.  If the result
18031914882SAlex Richardson    would be outside of [-2^31, 2^31-1] then the semantics is unspecified.  */
18131914882SAlex Richardson static inline double_t
18231914882SAlex Richardson roundtoint (double_t x)
18331914882SAlex Richardson {
18431914882SAlex Richardson   return round (x);
18531914882SAlex Richardson }
18631914882SAlex Richardson 
18731914882SAlex Richardson /* Convert x to nearest int in all rounding modes, ties have to be rounded
18831914882SAlex Richardson    consistently with roundtoint.  If the result is not representible in an
18931914882SAlex Richardson    int32_t then the semantics is unspecified.  */
19031914882SAlex Richardson static inline int32_t
19131914882SAlex Richardson converttoint (double_t x)
19231914882SAlex Richardson {
19331914882SAlex Richardson # if HAVE_FAST_LROUND
19431914882SAlex Richardson   return lround (x);
19531914882SAlex Richardson # else
19631914882SAlex Richardson   return (long) round (x);
19731914882SAlex Richardson # endif
19831914882SAlex Richardson }
19931914882SAlex Richardson #endif
20031914882SAlex Richardson 
20131914882SAlex Richardson static inline uint32_t
20231914882SAlex Richardson asuint (float f)
20331914882SAlex Richardson {
20431914882SAlex Richardson   union
20531914882SAlex Richardson   {
20631914882SAlex Richardson     float f;
20731914882SAlex Richardson     uint32_t i;
20831914882SAlex Richardson   } u = {f};
20931914882SAlex Richardson   return u.i;
21031914882SAlex Richardson }
21131914882SAlex Richardson 
21231914882SAlex Richardson static inline float
21331914882SAlex Richardson asfloat (uint32_t i)
21431914882SAlex Richardson {
21531914882SAlex Richardson   union
21631914882SAlex Richardson   {
21731914882SAlex Richardson     uint32_t i;
21831914882SAlex Richardson     float f;
21931914882SAlex Richardson   } u = {i};
22031914882SAlex Richardson   return u.f;
22131914882SAlex Richardson }
22231914882SAlex Richardson 
22331914882SAlex Richardson static inline uint64_t
22431914882SAlex Richardson asuint64 (double f)
22531914882SAlex Richardson {
22631914882SAlex Richardson   union
22731914882SAlex Richardson   {
22831914882SAlex Richardson     double f;
22931914882SAlex Richardson     uint64_t i;
23031914882SAlex Richardson   } u = {f};
23131914882SAlex Richardson   return u.i;
23231914882SAlex Richardson }
23331914882SAlex Richardson 
23431914882SAlex Richardson static inline double
23531914882SAlex Richardson asdouble (uint64_t i)
23631914882SAlex Richardson {
23731914882SAlex Richardson   union
23831914882SAlex Richardson   {
23931914882SAlex Richardson     uint64_t i;
24031914882SAlex Richardson     double f;
24131914882SAlex Richardson   } u = {i};
24231914882SAlex Richardson   return u.f;
24331914882SAlex Richardson }
24431914882SAlex Richardson 
24531914882SAlex Richardson #ifndef IEEE_754_2008_SNAN
24631914882SAlex Richardson # define IEEE_754_2008_SNAN 1
24731914882SAlex Richardson #endif
24831914882SAlex Richardson static inline int
24931914882SAlex Richardson issignalingf_inline (float x)
25031914882SAlex Richardson {
25131914882SAlex Richardson   uint32_t ix = asuint (x);
25231914882SAlex Richardson   if (!IEEE_754_2008_SNAN)
25331914882SAlex Richardson     return (ix & 0x7fc00000) == 0x7fc00000;
25431914882SAlex Richardson   return 2 * (ix ^ 0x00400000) > 2u * 0x7fc00000;
25531914882SAlex Richardson }
25631914882SAlex Richardson 
25731914882SAlex Richardson static inline int
25831914882SAlex Richardson issignaling_inline (double x)
25931914882SAlex Richardson {
26031914882SAlex Richardson   uint64_t ix = asuint64 (x);
26131914882SAlex Richardson   if (!IEEE_754_2008_SNAN)
26231914882SAlex Richardson     return (ix & 0x7ff8000000000000) == 0x7ff8000000000000;
26331914882SAlex Richardson   return 2 * (ix ^ 0x0008000000000000) > 2 * 0x7ff8000000000000ULL;
26431914882SAlex Richardson }
26531914882SAlex Richardson 
26631914882SAlex Richardson #if __aarch64__ && __GNUC__
26731914882SAlex Richardson /* Prevent the optimization of a floating-point expression.  */
26831914882SAlex Richardson static inline float
26931914882SAlex Richardson opt_barrier_float (float x)
27031914882SAlex Richardson {
27131914882SAlex Richardson   __asm__ __volatile__ ("" : "+w" (x));
27231914882SAlex Richardson   return x;
27331914882SAlex Richardson }
27431914882SAlex Richardson static inline double
27531914882SAlex Richardson opt_barrier_double (double x)
27631914882SAlex Richardson {
27731914882SAlex Richardson   __asm__ __volatile__ ("" : "+w" (x));
27831914882SAlex Richardson   return x;
27931914882SAlex Richardson }
28031914882SAlex Richardson /* Force the evaluation of a floating-point expression for its side-effect.  */
28131914882SAlex Richardson static inline void
28231914882SAlex Richardson force_eval_float (float x)
28331914882SAlex Richardson {
28431914882SAlex Richardson   __asm__ __volatile__ ("" : "+w" (x));
28531914882SAlex Richardson }
28631914882SAlex Richardson static inline void
28731914882SAlex Richardson force_eval_double (double x)
28831914882SAlex Richardson {
28931914882SAlex Richardson   __asm__ __volatile__ ("" : "+w" (x));
29031914882SAlex Richardson }
29131914882SAlex Richardson #else
29231914882SAlex Richardson static inline float
29331914882SAlex Richardson opt_barrier_float (float x)
29431914882SAlex Richardson {
29531914882SAlex Richardson   volatile float y = x;
29631914882SAlex Richardson   return y;
29731914882SAlex Richardson }
29831914882SAlex Richardson static inline double
29931914882SAlex Richardson opt_barrier_double (double x)
30031914882SAlex Richardson {
30131914882SAlex Richardson   volatile double y = x;
30231914882SAlex Richardson   return y;
30331914882SAlex Richardson }
30431914882SAlex Richardson static inline void
30531914882SAlex Richardson force_eval_float (float x)
30631914882SAlex Richardson {
30731914882SAlex Richardson   volatile float y UNUSED = x;
30831914882SAlex Richardson }
30931914882SAlex Richardson static inline void
31031914882SAlex Richardson force_eval_double (double x)
31131914882SAlex Richardson {
31231914882SAlex Richardson   volatile double y UNUSED = x;
31331914882SAlex Richardson }
31431914882SAlex Richardson #endif
31531914882SAlex Richardson 
31631914882SAlex Richardson /* Evaluate an expression as the specified type, normally a type
31731914882SAlex Richardson    cast should be enough, but compilers implement non-standard
31831914882SAlex Richardson    excess-precision handling, so when FLT_EVAL_METHOD != 0 then
31931914882SAlex Richardson    these functions may need to be customized.  */
32031914882SAlex Richardson static inline float
32131914882SAlex Richardson eval_as_float (float x)
32231914882SAlex Richardson {
32331914882SAlex Richardson   return x;
32431914882SAlex Richardson }
32531914882SAlex Richardson static inline double
32631914882SAlex Richardson eval_as_double (double x)
32731914882SAlex Richardson {
32831914882SAlex Richardson   return x;
32931914882SAlex Richardson }
33031914882SAlex Richardson 
33131914882SAlex Richardson /* Error handling tail calls for special cases, with a sign argument.
33231914882SAlex Richardson    The sign of the return value is set if the argument is non-zero.  */
33331914882SAlex Richardson 
33431914882SAlex Richardson /* The result overflows.  */
33531914882SAlex Richardson HIDDEN float __math_oflowf (uint32_t);
33631914882SAlex Richardson /* The result underflows to 0 in nearest rounding mode.  */
33731914882SAlex Richardson HIDDEN float __math_uflowf (uint32_t);
33831914882SAlex Richardson /* The result underflows to 0 in some directed rounding mode only.  */
33931914882SAlex Richardson HIDDEN float __math_may_uflowf (uint32_t);
34031914882SAlex Richardson /* Division by zero.  */
34131914882SAlex Richardson HIDDEN float __math_divzerof (uint32_t);
34231914882SAlex Richardson /* The result overflows.  */
34331914882SAlex Richardson HIDDEN double __math_oflow (uint32_t);
34431914882SAlex Richardson /* The result underflows to 0 in nearest rounding mode.  */
34531914882SAlex Richardson HIDDEN double __math_uflow (uint32_t);
34631914882SAlex Richardson /* The result underflows to 0 in some directed rounding mode only.  */
34731914882SAlex Richardson HIDDEN double __math_may_uflow (uint32_t);
34831914882SAlex Richardson /* Division by zero.  */
34931914882SAlex Richardson HIDDEN double __math_divzero (uint32_t);
35031914882SAlex Richardson 
35131914882SAlex Richardson /* Error handling using input checking.  */
35231914882SAlex Richardson 
35331914882SAlex Richardson /* Invalid input unless it is a quiet NaN.  */
35431914882SAlex Richardson HIDDEN float __math_invalidf (float);
35531914882SAlex Richardson /* Invalid input unless it is a quiet NaN.  */
35631914882SAlex Richardson HIDDEN double __math_invalid (double);
35731914882SAlex Richardson 
35831914882SAlex Richardson /* Error handling using output checking, only for errno setting.  */
35931914882SAlex Richardson 
36031914882SAlex Richardson /* Check if the result overflowed to infinity.  */
36131914882SAlex Richardson HIDDEN double __math_check_oflow (double);
36231914882SAlex Richardson /* Check if the result underflowed to 0.  */
36331914882SAlex Richardson HIDDEN double __math_check_uflow (double);
36431914882SAlex Richardson 
36531914882SAlex Richardson /* Check if the result overflowed to infinity.  */
36631914882SAlex Richardson static inline double
36731914882SAlex Richardson check_oflow (double x)
36831914882SAlex Richardson {
36931914882SAlex Richardson   return WANT_ERRNO ? __math_check_oflow (x) : x;
37031914882SAlex Richardson }
37131914882SAlex Richardson 
37231914882SAlex Richardson /* Check if the result underflowed to 0.  */
37331914882SAlex Richardson static inline double
37431914882SAlex Richardson check_uflow (double x)
37531914882SAlex Richardson {
37631914882SAlex Richardson   return WANT_ERRNO ? __math_check_uflow (x) : x;
37731914882SAlex Richardson }
37831914882SAlex Richardson 
37931914882SAlex Richardson /* Check if the result overflowed to infinity.  */
38031914882SAlex Richardson HIDDEN float __math_check_oflowf (float);
38131914882SAlex Richardson /* Check if the result underflowed to 0.  */
38231914882SAlex Richardson HIDDEN float __math_check_uflowf (float);
38331914882SAlex Richardson 
38431914882SAlex Richardson /* Check if the result overflowed to infinity.  */
38531914882SAlex Richardson static inline float
38631914882SAlex Richardson check_oflowf (float x)
38731914882SAlex Richardson {
38831914882SAlex Richardson   return WANT_ERRNO ? __math_check_oflowf (x) : x;
38931914882SAlex Richardson }
39031914882SAlex Richardson 
39131914882SAlex Richardson /* Check if the result underflowed to 0.  */
39231914882SAlex Richardson static inline float
39331914882SAlex Richardson check_uflowf (float x)
39431914882SAlex Richardson {
39531914882SAlex Richardson   return WANT_ERRNO ? __math_check_uflowf (x) : x;
39631914882SAlex Richardson }
39731914882SAlex Richardson 
39831914882SAlex Richardson /* Shared between expf, exp2f and powf.  */
39931914882SAlex Richardson #define EXP2F_TABLE_BITS 5
40031914882SAlex Richardson #define EXP2F_POLY_ORDER 3
40131914882SAlex Richardson extern const struct exp2f_data
40231914882SAlex Richardson {
40331914882SAlex Richardson   uint64_t tab[1 << EXP2F_TABLE_BITS];
40431914882SAlex Richardson   double shift_scaled;
40531914882SAlex Richardson   double poly[EXP2F_POLY_ORDER];
40631914882SAlex Richardson   double invln2_scaled;
40731914882SAlex Richardson   double poly_scaled[EXP2F_POLY_ORDER];
408*f3087befSAndrew Turner   double shift;
40931914882SAlex Richardson } __exp2f_data HIDDEN;
41031914882SAlex Richardson 
411*f3087befSAndrew Turner /* Data for logf and log10f.  */
41231914882SAlex Richardson #define LOGF_TABLE_BITS 4
41331914882SAlex Richardson #define LOGF_POLY_ORDER 4
41431914882SAlex Richardson extern const struct logf_data
41531914882SAlex Richardson {
41631914882SAlex Richardson   struct
41731914882SAlex Richardson   {
41831914882SAlex Richardson     double invc, logc;
41931914882SAlex Richardson   } tab[1 << LOGF_TABLE_BITS];
42031914882SAlex Richardson   double ln2;
421*f3087befSAndrew Turner   double invln10;
42231914882SAlex Richardson   double poly[LOGF_POLY_ORDER - 1]; /* First order coefficient is 1.  */
42331914882SAlex Richardson } __logf_data HIDDEN;
42431914882SAlex Richardson 
42531914882SAlex Richardson #define LOG2F_TABLE_BITS 4
42631914882SAlex Richardson #define LOG2F_POLY_ORDER 4
42731914882SAlex Richardson extern const struct log2f_data
42831914882SAlex Richardson {
42931914882SAlex Richardson   struct
43031914882SAlex Richardson   {
43131914882SAlex Richardson     double invc, logc;
43231914882SAlex Richardson   } tab[1 << LOG2F_TABLE_BITS];
43331914882SAlex Richardson   double poly[LOG2F_POLY_ORDER];
43431914882SAlex Richardson } __log2f_data HIDDEN;
43531914882SAlex Richardson 
43631914882SAlex Richardson #define POWF_LOG2_TABLE_BITS 4
43731914882SAlex Richardson #define POWF_LOG2_POLY_ORDER 5
43831914882SAlex Richardson #if TOINT_INTRINSICS
43931914882SAlex Richardson # define POWF_SCALE_BITS EXP2F_TABLE_BITS
44031914882SAlex Richardson #else
44131914882SAlex Richardson # define POWF_SCALE_BITS 0
44231914882SAlex Richardson #endif
44331914882SAlex Richardson #define POWF_SCALE ((double) (1 << POWF_SCALE_BITS))
44431914882SAlex Richardson extern const struct powf_log2_data
44531914882SAlex Richardson {
44631914882SAlex Richardson   struct
44731914882SAlex Richardson   {
44831914882SAlex Richardson     double invc, logc;
44931914882SAlex Richardson   } tab[1 << POWF_LOG2_TABLE_BITS];
45031914882SAlex Richardson   double poly[POWF_LOG2_POLY_ORDER];
45131914882SAlex Richardson } __powf_log2_data HIDDEN;
45231914882SAlex Richardson 
45331914882SAlex Richardson 
45431914882SAlex Richardson #define EXP_TABLE_BITS 7
45531914882SAlex Richardson #define EXP_POLY_ORDER 5
45631914882SAlex Richardson /* Use polynomial that is optimized for a wider input range.  This may be
45731914882SAlex Richardson    needed for good precision in non-nearest rounding and !TOINT_INTRINSICS.  */
45831914882SAlex Richardson #define EXP_POLY_WIDE 0
45931914882SAlex Richardson /* Use close to nearest rounding toint when !TOINT_INTRINSICS.  This may be
46031914882SAlex Richardson    needed for good precision in non-nearest rouning and !EXP_POLY_WIDE.  */
46131914882SAlex Richardson #define EXP_USE_TOINT_NARROW 0
46231914882SAlex Richardson #define EXP2_POLY_ORDER 5
46331914882SAlex Richardson #define EXP2_POLY_WIDE 0
4645a02ffc3SAndrew Turner /* Wider exp10 polynomial necessary for good precision in non-nearest rounding
4655a02ffc3SAndrew Turner    and !TOINT_INTRINSICS.  */
4665a02ffc3SAndrew Turner #define EXP10_POLY_WIDE 0
46731914882SAlex Richardson extern const struct exp_data
46831914882SAlex Richardson {
46931914882SAlex Richardson   double invln2N;
47031914882SAlex Richardson   double negln2hiN;
47131914882SAlex Richardson   double negln2loN;
47231914882SAlex Richardson   double poly[4]; /* Last four coefficients.  */
473*f3087befSAndrew Turner   double shift;
474*f3087befSAndrew Turner 
47531914882SAlex Richardson   double exp2_shift;
47631914882SAlex Richardson   double exp2_poly[EXP2_POLY_ORDER];
477*f3087befSAndrew Turner 
478*f3087befSAndrew Turner   double neglog10_2hiN;
479*f3087befSAndrew Turner   double neglog10_2loN;
4805a02ffc3SAndrew Turner   double exp10_poly[5];
48131914882SAlex Richardson   uint64_t tab[2*(1 << EXP_TABLE_BITS)];
482*f3087befSAndrew Turner   double invlog10_2N;
48331914882SAlex Richardson } __exp_data HIDDEN;
48431914882SAlex Richardson 
48531914882SAlex Richardson #define LOG_TABLE_BITS 7
48631914882SAlex Richardson #define LOG_POLY_ORDER 6
48731914882SAlex Richardson #define LOG_POLY1_ORDER 12
48831914882SAlex Richardson extern const struct log_data
48931914882SAlex Richardson {
49031914882SAlex Richardson   double ln2hi;
49131914882SAlex Richardson   double ln2lo;
49231914882SAlex Richardson   double poly[LOG_POLY_ORDER - 1]; /* First coefficient is 1.  */
49331914882SAlex Richardson   double poly1[LOG_POLY1_ORDER - 1];
49431914882SAlex Richardson   struct {double invc, logc;} tab[1 << LOG_TABLE_BITS];
49531914882SAlex Richardson #if !HAVE_FAST_FMA
49631914882SAlex Richardson   struct {double chi, clo;} tab2[1 << LOG_TABLE_BITS];
49731914882SAlex Richardson #endif
49831914882SAlex Richardson } __log_data HIDDEN;
49931914882SAlex Richardson 
50031914882SAlex Richardson #define LOG2_TABLE_BITS 6
50131914882SAlex Richardson #define LOG2_POLY_ORDER 7
50231914882SAlex Richardson #define LOG2_POLY1_ORDER 11
50331914882SAlex Richardson extern const struct log2_data
50431914882SAlex Richardson {
50531914882SAlex Richardson   double invln2hi;
50631914882SAlex Richardson   double invln2lo;
50731914882SAlex Richardson   double poly[LOG2_POLY_ORDER - 1];
50831914882SAlex Richardson   double poly1[LOG2_POLY1_ORDER - 1];
50931914882SAlex Richardson   struct {double invc, logc;} tab[1 << LOG2_TABLE_BITS];
51031914882SAlex Richardson #if !HAVE_FAST_FMA
51131914882SAlex Richardson   struct {double chi, clo;} tab2[1 << LOG2_TABLE_BITS];
51231914882SAlex Richardson #endif
51331914882SAlex Richardson } __log2_data HIDDEN;
51431914882SAlex Richardson 
51531914882SAlex Richardson #define POW_LOG_TABLE_BITS 7
51631914882SAlex Richardson #define POW_LOG_POLY_ORDER 8
51731914882SAlex Richardson extern const struct pow_log_data
51831914882SAlex Richardson {
51931914882SAlex Richardson   double ln2hi;
52031914882SAlex Richardson   double ln2lo;
52131914882SAlex Richardson   double poly[POW_LOG_POLY_ORDER - 1]; /* First coefficient is 1.  */
52231914882SAlex Richardson   /* Note: the pad field is unused, but allows slightly faster indexing.  */
52331914882SAlex Richardson   struct {double invc, pad, logc, logctail;} tab[1 << POW_LOG_TABLE_BITS];
52431914882SAlex Richardson } __pow_log_data HIDDEN;
52531914882SAlex Richardson 
52631914882SAlex Richardson extern const struct erff_data
52731914882SAlex Richardson {
52831914882SAlex Richardson   float erff_poly_A[6];
52931914882SAlex Richardson   float erff_poly_B[7];
53031914882SAlex Richardson } __erff_data HIDDEN;
53131914882SAlex Richardson 
53231914882SAlex Richardson #define ERF_POLY_A_ORDER 19
53331914882SAlex Richardson #define ERF_POLY_A_NCOEFFS 10
53431914882SAlex Richardson #define ERFC_POLY_C_NCOEFFS 16
53531914882SAlex Richardson #define ERFC_POLY_D_NCOEFFS 18
53631914882SAlex Richardson #define ERFC_POLY_E_NCOEFFS 14
53731914882SAlex Richardson #define ERFC_POLY_F_NCOEFFS 17
53831914882SAlex Richardson extern const struct erf_data
53931914882SAlex Richardson {
54031914882SAlex Richardson   double erf_poly_A[ERF_POLY_A_NCOEFFS];
54131914882SAlex Richardson   double erf_ratio_N_A[5];
54231914882SAlex Richardson   double erf_ratio_D_A[5];
54331914882SAlex Richardson   double erf_ratio_N_B[7];
54431914882SAlex Richardson   double erf_ratio_D_B[6];
54531914882SAlex Richardson   double erfc_poly_C[ERFC_POLY_C_NCOEFFS];
54631914882SAlex Richardson   double erfc_poly_D[ERFC_POLY_D_NCOEFFS];
54731914882SAlex Richardson   double erfc_poly_E[ERFC_POLY_E_NCOEFFS];
54831914882SAlex Richardson   double erfc_poly_F[ERFC_POLY_F_NCOEFFS];
54931914882SAlex Richardson } __erf_data HIDDEN;
55031914882SAlex Richardson 
5515a02ffc3SAndrew Turner #define V_EXP_TABLE_BITS 7
5525a02ffc3SAndrew Turner extern const uint64_t __v_exp_data[1 << V_EXP_TABLE_BITS] HIDDEN;
5535a02ffc3SAndrew Turner 
554*f3087befSAndrew Turner #define V_LOG_POLY_ORDER 6
5555a02ffc3SAndrew Turner #define V_LOG_TABLE_BITS 7
5565a02ffc3SAndrew Turner extern const struct v_log_data
5575a02ffc3SAndrew Turner {
558*f3087befSAndrew Turner   /* Shared data for vector log and log-derived routines (e.g. asinh).  */
559*f3087befSAndrew Turner   double poly[V_LOG_POLY_ORDER - 1];
560*f3087befSAndrew Turner   double ln2;
5615a02ffc3SAndrew Turner   struct
5625a02ffc3SAndrew Turner   {
5635a02ffc3SAndrew Turner     double invc, logc;
5645a02ffc3SAndrew Turner   } table[1 << V_LOG_TABLE_BITS];
5655a02ffc3SAndrew Turner } __v_log_data HIDDEN;
5665a02ffc3SAndrew Turner 
567*f3087befSAndrew Turner /* Some data for SVE powf's internal exp and log.  */
568*f3087befSAndrew Turner #define V_POWF_EXP2_TABLE_BITS 5
569*f3087befSAndrew Turner #define V_POWF_EXP2_N (1 << V_POWF_EXP2_TABLE_BITS)
570*f3087befSAndrew Turner #define V_POWF_LOG2_TABLE_BITS 5
571*f3087befSAndrew Turner #define V_POWF_LOG2_N (1 << V_POWF_LOG2_TABLE_BITS)
572*f3087befSAndrew Turner extern const struct v_powf_data
573*f3087befSAndrew Turner {
574*f3087befSAndrew Turner   double invc[V_POWF_LOG2_N];
575*f3087befSAndrew Turner   double logc[V_POWF_LOG2_N];
576*f3087befSAndrew Turner   uint64_t scale[V_POWF_EXP2_N];
577*f3087befSAndrew Turner } __v_powf_data HIDDEN;
578*f3087befSAndrew Turner 
579*f3087befSAndrew Turner /* Some data for AdvSIMD and SVE pow's internal exp and log.  */
580*f3087befSAndrew Turner #define V_POW_EXP_TABLE_BITS 8
581*f3087befSAndrew Turner extern const struct v_pow_exp_data
582*f3087befSAndrew Turner {
583*f3087befSAndrew Turner   double poly[3];
584*f3087befSAndrew Turner   double n_over_ln2, ln2_over_n_hi, ln2_over_n_lo, shift;
585*f3087befSAndrew Turner   uint64_t sbits[1 << V_POW_EXP_TABLE_BITS];
586*f3087befSAndrew Turner } __v_pow_exp_data HIDDEN;
587*f3087befSAndrew Turner 
588*f3087befSAndrew Turner #define V_POW_LOG_TABLE_BITS 7
589*f3087befSAndrew Turner extern const struct v_pow_log_data
590*f3087befSAndrew Turner {
591*f3087befSAndrew Turner   double poly[7]; /* First coefficient is 1.  */
592*f3087befSAndrew Turner   double ln2_hi, ln2_lo;
593*f3087befSAndrew Turner   double invc[1 << V_POW_LOG_TABLE_BITS];
594*f3087befSAndrew Turner   double logc[1 << V_POW_LOG_TABLE_BITS];
595*f3087befSAndrew Turner   double logctail[1 << V_POW_LOG_TABLE_BITS];
596*f3087befSAndrew Turner } __v_pow_log_data HIDDEN;
597*f3087befSAndrew Turner 
598*f3087befSAndrew Turner #define V_LOG2_TABLE_BITS 7
599*f3087befSAndrew Turner extern const struct v_log2_data
600*f3087befSAndrew Turner {
601*f3087befSAndrew Turner   double poly[5];
602*f3087befSAndrew Turner   double invln2;
603*f3087befSAndrew Turner   struct
604*f3087befSAndrew Turner   {
605*f3087befSAndrew Turner     double invc, log2c;
606*f3087befSAndrew Turner   } table[1 << V_LOG2_TABLE_BITS];
607*f3087befSAndrew Turner } __v_log2_data HIDDEN;
608*f3087befSAndrew Turner 
609*f3087befSAndrew Turner #define V_LOG10_TABLE_BITS 7
610*f3087befSAndrew Turner extern const struct v_log10_data
611*f3087befSAndrew Turner {
612*f3087befSAndrew Turner   double poly[5];
613*f3087befSAndrew Turner   double invln10, log10_2;
614*f3087befSAndrew Turner   struct
615*f3087befSAndrew Turner   {
616*f3087befSAndrew Turner     double invc, log10c;
617*f3087befSAndrew Turner   } table[1 << V_LOG10_TABLE_BITS];
618*f3087befSAndrew Turner } __v_log10_data HIDDEN;
619*f3087befSAndrew Turner 
620*f3087befSAndrew Turner #define V_EXP_TAIL_TABLE_BITS 8
621*f3087befSAndrew Turner extern const uint64_t __v_exp_tail_data[1 << V_EXP_TAIL_TABLE_BITS] HIDDEN;
622*f3087befSAndrew Turner 
623*f3087befSAndrew Turner extern const struct v_erff_data
624*f3087befSAndrew Turner {
625*f3087befSAndrew Turner   struct
626*f3087befSAndrew Turner   {
627*f3087befSAndrew Turner     float erf, scale;
628*f3087befSAndrew Turner   } tab[513];
629*f3087befSAndrew Turner } __v_erff_data HIDDEN;
630*f3087befSAndrew Turner 
631*f3087befSAndrew Turner extern const struct v_erfcf_data
632*f3087befSAndrew Turner {
633*f3087befSAndrew Turner   struct
634*f3087befSAndrew Turner   {
635*f3087befSAndrew Turner     float erfc, scale;
636*f3087befSAndrew Turner   } tab[645];
637*f3087befSAndrew Turner } __v_erfcf_data HIDDEN;
638*f3087befSAndrew Turner 
639*f3087befSAndrew Turner extern const struct v_erf_data
640*f3087befSAndrew Turner {
641*f3087befSAndrew Turner   struct
642*f3087befSAndrew Turner   {
643*f3087befSAndrew Turner     double erf, scale;
644*f3087befSAndrew Turner   } tab[769];
645*f3087befSAndrew Turner } __v_erf_data HIDDEN;
646*f3087befSAndrew Turner 
647*f3087befSAndrew Turner extern const struct v_erfc_data
648*f3087befSAndrew Turner {
649*f3087befSAndrew Turner   struct
650*f3087befSAndrew Turner   {
651*f3087befSAndrew Turner     double erfc, scale;
652*f3087befSAndrew Turner   } tab[3488];
653*f3087befSAndrew Turner } __v_erfc_data HIDDEN;
654*f3087befSAndrew Turner 
655*f3087befSAndrew Turner /* Table with 4/PI to 192 bit precision.  */
656*f3087befSAndrew Turner extern const uint32_t __inv_pio4[] HIDDEN;
657*f3087befSAndrew Turner 
658*f3087befSAndrew Turner #if WANT_EXPERIMENTAL_MATH
659*f3087befSAndrew Turner 
660*f3087befSAndrew Turner # define LOG1P_NCOEFFS 19
661*f3087befSAndrew Turner extern const struct log1p_data
662*f3087befSAndrew Turner {
663*f3087befSAndrew Turner   double coeffs[LOG1P_NCOEFFS];
664*f3087befSAndrew Turner } __log1p_data HIDDEN;
665*f3087befSAndrew Turner 
666*f3087befSAndrew Turner # define LOG1PF_2U5
667*f3087befSAndrew Turner # define LOG1PF_NCOEFFS 9
668*f3087befSAndrew Turner extern const struct log1pf_data
669*f3087befSAndrew Turner {
670*f3087befSAndrew Turner   float coeffs[LOG1PF_NCOEFFS];
671*f3087befSAndrew Turner } __log1pf_data HIDDEN;
672*f3087befSAndrew Turner 
673*f3087befSAndrew Turner # define ASINF_POLY_ORDER 4
674*f3087befSAndrew Turner extern const float __asinf_poly[ASINF_POLY_ORDER + 1] HIDDEN;
675*f3087befSAndrew Turner 
676*f3087befSAndrew Turner # define ASIN_POLY_ORDER 11
677*f3087befSAndrew Turner extern const double __asin_poly[ASIN_POLY_ORDER + 1] HIDDEN;
678*f3087befSAndrew Turner 
679*f3087befSAndrew Turner # define ASINHF_NCOEFFS 8
680*f3087befSAndrew Turner extern const struct asinhf_data
681*f3087befSAndrew Turner {
682*f3087befSAndrew Turner   float coeffs[ASINHF_NCOEFFS];
683*f3087befSAndrew Turner } __asinhf_data HIDDEN;
684*f3087befSAndrew Turner 
685*f3087befSAndrew Turner # define ASINH_NCOEFFS 18
686*f3087befSAndrew Turner extern const struct asinh_data
687*f3087befSAndrew Turner {
688*f3087befSAndrew Turner   double poly[ASINH_NCOEFFS];
689*f3087befSAndrew Turner } __asinh_data HIDDEN;
690*f3087befSAndrew Turner 
691*f3087befSAndrew Turner # define ATAN_POLY_NCOEFFS 20
692*f3087befSAndrew Turner extern const struct atan_poly_data
693*f3087befSAndrew Turner {
694*f3087befSAndrew Turner   double poly[ATAN_POLY_NCOEFFS];
695*f3087befSAndrew Turner } __atan_poly_data HIDDEN;
696*f3087befSAndrew Turner 
697*f3087befSAndrew Turner # define ATANF_POLY_NCOEFFS 8
698*f3087befSAndrew Turner extern const struct atanf_poly_data
699*f3087befSAndrew Turner {
700*f3087befSAndrew Turner   float poly[ATANF_POLY_NCOEFFS];
701*f3087befSAndrew Turner } __atanf_poly_data HIDDEN;
702*f3087befSAndrew Turner 
703*f3087befSAndrew Turner extern const struct cbrtf_data
704*f3087befSAndrew Turner {
705*f3087befSAndrew Turner   float poly[4];
706*f3087befSAndrew Turner   float table[5];
707*f3087befSAndrew Turner } __cbrtf_data HIDDEN;
708*f3087befSAndrew Turner 
709*f3087befSAndrew Turner extern const struct cbrt_data
710*f3087befSAndrew Turner {
711*f3087befSAndrew Turner   double poly[4];
712*f3087befSAndrew Turner   double table[5];
713*f3087befSAndrew Turner } __cbrt_data HIDDEN;
714*f3087befSAndrew Turner 
715*f3087befSAndrew Turner # define EXPF_TABLE_BITS 5
716*f3087befSAndrew Turner # define EXPF_POLY_ORDER 3
717*f3087befSAndrew Turner extern const struct expf_data
718*f3087befSAndrew Turner {
719*f3087befSAndrew Turner   uint64_t tab[1 << EXPF_TABLE_BITS];
720*f3087befSAndrew Turner   double invln2_scaled;
721*f3087befSAndrew Turner   double poly_scaled[EXPF_POLY_ORDER];
722*f3087befSAndrew Turner } __expf_data HIDDEN;
723*f3087befSAndrew Turner 
724*f3087befSAndrew Turner # define EXPM1F_POLY_ORDER 5
725*f3087befSAndrew Turner extern const float __expm1f_poly[EXPM1F_POLY_ORDER] HIDDEN;
726*f3087befSAndrew Turner 
727*f3087befSAndrew Turner # define EXPM1_POLY_ORDER 11
728*f3087befSAndrew Turner extern const double __expm1_poly[EXPM1_POLY_ORDER] HIDDEN;
729*f3087befSAndrew Turner 
730*f3087befSAndrew Turner /* Data for low accuracy log10 (with 1/ln(10) included in coefficients).  */
731*f3087befSAndrew Turner # define LOG10_TABLE_BITS 7
732*f3087befSAndrew Turner # define LOG10_POLY_ORDER 6
733*f3087befSAndrew Turner # define LOG10_POLY1_ORDER 12
734*f3087befSAndrew Turner extern const struct log10_data
735*f3087befSAndrew Turner {
736*f3087befSAndrew Turner   double ln2hi;
737*f3087befSAndrew Turner   double ln2lo;
738*f3087befSAndrew Turner   double invln10;
739*f3087befSAndrew Turner   double poly[LOG10_POLY_ORDER - 1]; /* First coefficient is 1/log(10).  */
740*f3087befSAndrew Turner   double poly1[LOG10_POLY1_ORDER - 1];
741*f3087befSAndrew Turner   struct
742*f3087befSAndrew Turner   {
743*f3087befSAndrew Turner     double invc, logc;
744*f3087befSAndrew Turner   } tab[1 << LOG10_TABLE_BITS];
745*f3087befSAndrew Turner #  if !HAVE_FAST_FMA
746*f3087befSAndrew Turner   struct
747*f3087befSAndrew Turner   {
748*f3087befSAndrew Turner     double chi, clo;
749*f3087befSAndrew Turner   } tab2[1 << LOG10_TABLE_BITS];
750*f3087befSAndrew Turner #  endif
751*f3087befSAndrew Turner } __log10_data HIDDEN;
752*f3087befSAndrew Turner 
753*f3087befSAndrew Turner # define TANF_P_POLY_NCOEFFS 6
754*f3087befSAndrew Turner /* cotan approach needs order 3 on [0, pi/4] to reach <3.5ulps.  */
755*f3087befSAndrew Turner # define TANF_Q_POLY_NCOEFFS 4
756*f3087befSAndrew Turner extern const struct tanf_poly_data
757*f3087befSAndrew Turner {
758*f3087befSAndrew Turner   float poly_tan[TANF_P_POLY_NCOEFFS];
759*f3087befSAndrew Turner   float poly_cotan[TANF_Q_POLY_NCOEFFS];
760*f3087befSAndrew Turner } __tanf_poly_data HIDDEN;
761*f3087befSAndrew Turner 
762*f3087befSAndrew Turner #endif /* WANT_EXPERIMENTAL_MATH.  */
763*f3087befSAndrew Turner 
76431914882SAlex Richardson #endif
765