#ifndef _MATH_PRIVATE_H_
#define _MATH_PRIVATE_H_
#include <assert.h>
#include <sys/types.h>
#include <sys/endian.h>
#ifdef __arm__
#if defined(__VFP_FP__) || defined(__ARM_EABI__)
#define IEEE_WORD_ORDER BYTE_ORDER
#else
#define IEEE_WORD_ORDER BIG_ENDIAN
#endif
#else
#define IEEE_WORD_ORDER BYTE_ORDER
#endif
#if IEEE_WORD_ORDER == BIG_ENDIAN
typedef union
{
long double value;
struct {
u_int32_t mswhi;
u_int32_t mswlo;
u_int32_t lswhi;
u_int32_t lswlo;
} parts32;
struct {
u_int64_t msw;
u_int64_t lsw;
} parts64;
} ieee_quad_shape_type;
#endif
#if IEEE_WORD_ORDER == LITTLE_ENDIAN
typedef union
{
long double value;
struct {
u_int32_t lswlo;
u_int32_t lswhi;
u_int32_t mswlo;
u_int32_t mswhi;
} parts32;
struct {
u_int64_t lsw;
u_int64_t msw;
} parts64;
} ieee_quad_shape_type;
#endif
#if IEEE_WORD_ORDER == BIG_ENDIAN
typedef union
{
double value;
struct
{
u_int32_t msw;
u_int32_t lsw;
} parts;
struct
{
u_int64_t w;
} xparts;
} ieee_double_shape_type;
#endif
#if IEEE_WORD_ORDER == LITTLE_ENDIAN
typedef union
{
double value;
struct
{
u_int32_t lsw;
u_int32_t msw;
} parts;
struct
{
u_int64_t w;
} xparts;
} ieee_double_shape_type;
#endif
#define EXTRACT_WORDS(ix0,ix1,d) \
do { \
ieee_double_shape_type ew_u; \
ew_u.value = (d); \
(ix0) = ew_u.parts.msw; \
(ix1) = ew_u.parts.lsw; \
} while (0)
#define EXTRACT_WORD64(ix,d) \
do { \
ieee_double_shape_type ew_u; \
ew_u.value = (d); \
(ix) = ew_u.xparts.w; \
} while (0)
#define GET_HIGH_WORD(i,d) \
do { \
ieee_double_shape_type gh_u; \
gh_u.value = (d); \
(i) = gh_u.parts.msw; \
} while (0)
#define GET_LOW_WORD(i,d) \
do { \
ieee_double_shape_type gl_u; \
gl_u.value = (d); \
(i) = gl_u.parts.lsw; \
} while (0)
#define INSERT_WORDS(d,ix0,ix1) \
do { \
ieee_double_shape_type iw_u; \
iw_u.parts.msw = (ix0); \
iw_u.parts.lsw = (ix1); \
(d) = iw_u.value; \
} while (0)
#define INSERT_WORD64(d,ix) \
do { \
ieee_double_shape_type iw_u; \
iw_u.xparts.w = (ix); \
(d) = iw_u.value; \
} while (0)
#define SET_HIGH_WORD(d,v) \
do { \
ieee_double_shape_type sh_u; \
sh_u.value = (d); \
sh_u.parts.msw = (v); \
(d) = sh_u.value; \
} while (0)
#define SET_LOW_WORD(d,v) \
do { \
ieee_double_shape_type sl_u; \
sl_u.value = (d); \
sl_u.parts.lsw = (v); \
(d) = sl_u.value; \
} while (0)
typedef union
{
float value;
u_int32_t word;
} ieee_float_shape_type;
#define GET_FLOAT_WORD(i,d) \
do { \
ieee_float_shape_type gf_u; \
gf_u.value = (d); \
(i) = gf_u.word; \
} while (0)
#define SET_FLOAT_WORD(d,i) \
do { \
ieee_float_shape_type sf_u; \
sf_u.word = (i); \
(d) = sf_u.value; \
} while (0)
#define GET_EXPSIGN(u) \
(((u)->extu_sign << EXT_EXPBITS) | (u)->extu_exp)
#define SET_EXPSIGN(u, x) \
(u)->extu_exp = (x), \
(u)->extu_sign = ((x) >> EXT_EXPBITS)
#define GET_LDBL80_MAN(u) \
(((uint64_t)(u)->extu_frach << EXT_FRACLBITS) | (u)->extu_fracl)
#define SET_LDBL80_MAN(u, v) \
((u)->extu_fracl = (v) & ((1ULL << EXT_FRACLBITS) - 1), \
(u)->extu_frach = (v) >> EXT_FRACLBITS)
#define EXTRACT_LDBL80_WORDS(ix0,ix1,d) \
do { \
union ieee_ext_u ew_u; \
ew_u.extu_ld = (d); \
(ix0) = GET_EXPSIGN(&ew_u); \
(ix1) = GET_LDBL80_MAN(&ew_u); \
} while (0)
#define EXTRACT_LDBL128_WORDS(ix0,ix1,ix2,d) \
do { \
union ieee_ext_u ew_u; \
ew_u.extu_ld = (d); \
(ix0) = GET_EXPSIGN(&ew_u); \
(ix1) = ew_u.extu_frach; \
(ix2) = ew_u.extu_fracl; \
} while (0)
#define GET_LDBL_EXPSIGN(i,d) \
do { \
union ieee_ext_u ge_u; \
ge_u.extu_ld = (d); \
(i) = GET_EXPSIGN(&ge_u); \
} while (0)
#define INSERT_LDBL80_WORDS(d,ix0,ix1) \
do { \
union ieee_ext_u iw_u; \
SET_EXPSIGN(&iw_u, ix0); \
SET_LDBL80_MAN(&iw_u, ix1); \
(d) = iw_u.extu_ld; \
} while (0)
#define INSERT_LDBL128_WORDS(d,ix0,ix1,ix2) \
do { \
union ieee_ext_u iw_u; \
SET_EXPSIGN(&iw_u, ix0); \
iw_u.extu_frach = (ix1); \
iw_u.extu_fracl = (ix2); \
(d) = iw_u.extu_ld; \
} while (0)
#define SET_LDBL_EXPSIGN(d,v) \
do { \
union ieee_ext_u se_u; \
se_u.extu_ld = (d); \
SET_EXPSIGN(&se_u, v); \
(d) = se_u.extu_ld; \
} while (0)
#ifdef __i386__
#define LD80C(m, ex, v) { \
.extu_fracl = (uint32_t)(__CONCAT(m, ULL)), \
.extu_frach = __CONCAT(m, ULL) >> EXT_FRACLBITS, \
.extu_exp = (0x3fff + (ex)), \
.extu_sign = ((v) < 0), \
}
#else
#define LD80C(m, ex, v) { .extu_ld = (v), }
#endif
#if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
#else
#define STRICT_ASSIGN(type, lval, rval) do { \
volatile type __lval; \
\
if (sizeof(type) >= sizeof(long double)) \
(lval) = (rval); \
else { \
__lval = (rval); \
(lval) = __lval; \
} \
} while (0)
#endif
#if defined(__i386__) && !defined(NO_FPSETPREC)
#include <ieeefp.h>
#define ENTERI() ENTERIT(long double)
#define ENTERIT(returntype) \
returntype __retval; \
fp_prec_t __oprec; \
\
if ((__oprec = fpgetprec()) != FP_PE) \
fpsetprec(FP_PE)
#define RETURNI(x) do { \
__retval = (x); \
if (__oprec != FP_PE) \
fpsetprec(__oprec); \
RETURNF(__retval); \
} while (0)
#define ENTERV() \
fp_prec_t __oprec; \
\
if ((__oprec = fpgetprec()) != FP_PE) \
fpsetprec(FP_PE)
#define RETURNV() do { \
if (__oprec != FP_PE) \
fpsetprec(__oprec); \
return; \
} while (0)
#else
#define ENTERI()
#define ENTERIT(x)
#define RETURNI(x) RETURNF(x)
#define ENTERV()
#define RETURNV() return
#endif
#define RETURNF(v) return (v)
#define _2sum(a, b) do { \
__typeof(a) __s, __w; \
\
__w = (a) + (b); \
__s = __w - (a); \
(b) = ((a) - (__w - __s)) + ((b) - __s); \
(a) = __w; \
} while (0)
#ifdef DEBUG
#define _2sumF(a, b) do { \
__typeof(a) __w; \
volatile __typeof(a) __ia, __ib, __r, __vw; \
\
__ia = (a); \
__ib = (b); \
assert(__ia == 0 || fabsl(__ia) >= fabsl(__ib)); \
\
__w = (a) + (b); \
(b) = ((a) - __w) + (b); \
(a) = __w; \
\
\
assert((long double)__ia + __ib == (long double)(a) + (b)); \
__vw = __ia + __ib; \
__r = __ia - __vw; \
__r += __ib; \
assert(__vw == (a) && __r == (b)); \
} while (0)
#else
#define _2sumF(a, b) do { \
__typeof(a) __w; \
\
__w = (a) + (b); \
(b) = ((a) - __w) + (b); \
(a) = __w; \
} while (0)
#endif
#define _3sumF(a, b, c) do { \
__typeof(a) __tmp; \
\
__tmp = (c); \
_2sumF(__tmp, (a)); \
(b) += (a); \
(a) = __tmp; \
} while (0)
void _scan_nan(uint32_t *__words, int __num_words, const char *__s);
#define nan_mix(x, y) (nan_mix_op((x), (y), +))
#define nan_mix_op(x, y, op) (((x) + 0.0L) op ((y) + 0))
#ifdef _COMPLEX_H
typedef union {
float complex z;
float parts[2];
} float_complex;
typedef union {
double complex z;
double parts[2];
} double_complex;
typedef union {
long double complex z;
long double parts[2];
} long_double_complex;
#define REAL_PART(z) ((z).parts[0])
#define IMAG_PART(z) ((z).parts[1])
#ifndef CMPLXF
static __inline float complex
CMPLXF(float x, float y)
{
float_complex z;
REAL_PART(z) = x;
IMAG_PART(z) = y;
return (z.z);
}
#endif
#ifndef CMPLX
static __inline double complex
CMPLX(double x, double y)
{
double_complex z;
REAL_PART(z) = x;
IMAG_PART(z) = y;
return (z.z);
}
#endif
#ifndef CMPLXL
static __inline long double complex
CMPLXL(long double x, long double y)
{
long_double_complex z;
REAL_PART(z) = x;
IMAG_PART(z) = y;
return (z.z);
}
#endif
#endif
extern double __ieee754_sqrt __P((double));
extern double __ieee754_acos __P((double));
extern double __ieee754_acosh __P((double));
extern double __ieee754_log __P((double));
extern double __ieee754_atanh __P((double));
extern double __ieee754_asin __P((double));
extern double __ieee754_atan2 __P((double,double));
extern double __ieee754_exp __P((double));
extern double __ieee754_cosh __P((double));
extern double __ieee754_fmod __P((double,double));
extern double __ieee754_pow __P((double,double));
extern double __ieee754_lgamma_r __P((double,int *));
extern double __ieee754_gamma_r __P((double,int *));
extern double __ieee754_lgamma __P((double));
extern double __ieee754_gamma __P((double));
extern double __ieee754_log10 __P((double));
extern double __ieee754_log2 __P((double));
extern double __ieee754_sinh __P((double));
extern double __ieee754_hypot __P((double,double));
extern double __ieee754_j0 __P((double));
extern double __ieee754_j1 __P((double));
extern double __ieee754_y0 __P((double));
extern double __ieee754_y1 __P((double));
extern double __ieee754_jn __P((int,double));
extern double __ieee754_yn __P((int,double));
extern double __ieee754_remainder __P((double,double));
extern int32_t __ieee754_rem_pio2 __P((double,double*));
extern double __ieee754_scalb __P((double,double));
extern double __kernel_standard __P((double,double,int));
extern double __kernel_sin __P((double,double,int));
extern double __kernel_cos __P((double,double));
extern double __kernel_tan __P((double,double,int));
extern int __kernel_rem_pio2 __P((double*,double*,int,int,int));
extern float __ieee754_sqrtf __P((float));
extern float __ieee754_acosf __P((float));
extern float __ieee754_acoshf __P((float));
extern float __ieee754_logf __P((float));
extern float __ieee754_atanhf __P((float));
extern float __ieee754_asinf __P((float));
extern float __ieee754_atan2f __P((float,float));
extern float __ieee754_expf __P((float));
extern float __ieee754_coshf __P((float));
extern float __ieee754_fmodf __P((float,float));
extern float __ieee754_powf __P((float,float));
extern float __ieee754_lgammaf_r __P((float,int *));
extern float __ieee754_gammaf_r __P((float,int *));
extern float __ieee754_lgammaf __P((float));
extern float __ieee754_gammaf __P((float));
extern float __ieee754_log10f __P((float));
extern float __ieee754_log2f __P((float));
extern float __ieee754_sinhf __P((float));
extern float __ieee754_hypotf __P((float,float));
extern float __ieee754_j0f __P((float));
extern float __ieee754_j1f __P((float));
extern float __ieee754_y0f __P((float));
extern float __ieee754_y1f __P((float));
extern float __ieee754_jnf __P((int,float));
extern float __ieee754_ynf __P((int,float));
extern float __ieee754_remainderf __P((float,float));
extern int32_t __ieee754_rem_pio2f __P((float,float*));
extern float __ieee754_scalbf __P((float,float));
extern float __kernel_sinf __P((float,float,int));
extern float __kernel_cosf __P((float,float));
extern float __kernel_tanf __P((float,float,int));
extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const int32_t*));
extern long double __ieee754_fmodl(long double, long double);
extern long double __ieee754_sqrtl(long double);
#define TRUNC(d) (_b_trunc(&(d)))
static __inline void
_b_trunc(volatile double *_dp)
{
uint32_t _lw;
GET_LOW_WORD(_lw, *_dp);
SET_LOW_WORD(*_dp, _lw & 0xf8000000);
}
struct Double {
double a;
double b;
};
double __exp__D(double, double);
struct Double __log__D(double);
static inline double
rnint(double x)
{
return ((double)(x + 0x1.8p52) - 0x1.8p52);
}
static inline float
rnintf(float x)
{
return ((float)(x + 0x1.8p23F) - 0x1.8p23F);
}
#ifdef LDBL_MANT_DIG
static inline long double
rnintl(long double x)
{
return (x + ___CONCAT(0x1.8p,LDBL_MANT_DIG) / 2 -
___CONCAT(0x1.8p,LDBL_MANT_DIG) / 2);
}
#endif
#if (defined(amd64) || defined(__i386__)) && defined(__GNUCLIKE_ASM)
#define irint(x) \
(sizeof(x) == sizeof(float) && \
sizeof(__float_t) == sizeof(long double) ? irintf(x) : \
sizeof(x) == sizeof(double) && \
sizeof(__double_t) == sizeof(long double) ? irintd(x) : \
sizeof(x) == sizeof(long double) ? irintl(x) : (int)(x))
#else
#define irint(x) ((int)(x))
#endif
#define i64rint(x) ((int64_t)(x))
#if defined(__i386__) && defined(__GNUCLIKE_ASM)
static __inline int
irintf(float x)
{
int n;
__asm("fistl %0" : "=m" (n) : "t" (x));
return (n);
}
static __inline int
irintd(double x)
{
int n;
__asm("fistl %0" : "=m" (n) : "t" (x));
return (n);
}
#endif
#if (defined(__amd64__) || defined(__i386__)) && defined(__GNUCLIKE_ASM)
static __inline int
irintl(long double x)
{
int n;
__asm("fistl %0" : "=m" (n) : "t" (x));
return (n);
}
#endif
#define FFLOORF(x, j0, ix) do { \
(j0) = (((ix) >> 23) & 0xff) - 0x7f; \
(ix) &= ~(0x007fffff >> (j0)); \
SET_FLOAT_WORD((x), (ix)); \
} while (0)
#define FFLOOR(x, j0, ix, lx) do { \
(j0) = (((ix) >> 20) & 0x7ff) - 0x3ff; \
if ((j0) < 20) { \
(ix) &= ~(0x000fffff >> (j0)); \
(lx) = 0; \
} else { \
(lx) &= ~((uint32_t)0xffffffff >> ((j0) - 20)); \
} \
INSERT_WORDS((x), (ix), (lx)); \
} while (0)
#define FFLOORL80(x, j0, ix, lx) do { \
j0 = ix - 0x3fff + 1; \
if ((j0) < 32) { \
(lx) = ((lx) >> 32) << 32; \
(lx) &= ~((((lx) << 32)-1) >> (j0)); \
} else { \
uint64_t _m; \
_m = (uint64_t)-1 >> (j0); \
if ((lx) & _m) (lx) &= ~_m; \
} \
INSERT_LDBL80_WORDS((x), (ix), (lx)); \
} while (0)
#define FFLOORL128(x, ai, ar) do { \
union ieee_ext_u u; \
uint64_t m; \
int e; \
u.extu_ld = (x); \
e = u.extu_exp - 16383; \
if (e < 48) { \
m = ((1llu << 49) - 1) >> (e + 1); \
u.extu_frach &= ~m; \
u.extu_fracl = 0; \
} else { \
m = (uint64_t)-1 >> (e - 48); \
u.extu_fracl &= ~m; \
} \
(ai) = u.extu_ld; \
(ar) = (x) - (ai); \
} while (0)
#ifdef DEBUG
#if defined(__amd64__) || defined(__i386__)
#define breakpoint() asm("int $3")
#else
#include <signal.h>
#define breakpoint() raise(SIGTRAP)
#endif
#endif
#ifdef STRUCT_RETURN
#define RETURNSP(rp) do { \
if (!(rp)->lo_set) \
RETURNF((rp)->hi); \
RETURNF((rp)->hi + (rp)->lo); \
} while (0)
#define RETURNSPI(rp) do { \
if (!(rp)->lo_set) \
RETURNI((rp)->hi); \
RETURNI((rp)->hi + (rp)->lo); \
} while (0)
#endif
#define SUM2P(x, y) ({ \
const __typeof (x) __x = (x); \
const __typeof (y) __y = (y); \
__x + __y; \
})
#ifndef INLINE_KERNEL_SINDF
float __kernel_sindf(double);
#endif
#ifndef INLINE_KERNEL_COSDF
float __kernel_cosdf(double);
#endif
#ifndef INLINE_KERNEL_TANDF
float __kernel_tandf(double,int);
#endif
long double __kernel_sinl(long double, long double, int);
long double __kernel_cosl(long double, long double);
long double __kernel_tanl(long double, long double, int);
#endif