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