12fe8fb19SBen Gras /*
22fe8fb19SBen Gras * ====================================================
32fe8fb19SBen Gras * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
42fe8fb19SBen Gras *
52fe8fb19SBen Gras * Developed at SunPro, a Sun Microsystems, Inc. business.
62fe8fb19SBen Gras * Permission to use, copy, modify, and distribute this
72fe8fb19SBen Gras * software is freely granted, provided that this notice
82fe8fb19SBen Gras * is preserved.
92fe8fb19SBen Gras * ====================================================
102fe8fb19SBen Gras */
112fe8fb19SBen Gras
122fe8fb19SBen Gras /*
132fe8fb19SBen Gras * from: @(#)fdlibm.h 5.1 93/09/24
14*0a6a1f1dSLionel Sambuc * $NetBSD: math_private.h,v 1.22 2015/03/26 11:59:38 justin Exp $
152fe8fb19SBen Gras */
162fe8fb19SBen Gras
172fe8fb19SBen Gras #ifndef _MATH_PRIVATE_H_
182fe8fb19SBen Gras #define _MATH_PRIVATE_H_
192fe8fb19SBen Gras
202fe8fb19SBen Gras #include <sys/types.h>
212fe8fb19SBen Gras
222fe8fb19SBen Gras /* The original fdlibm code used statements like:
232fe8fb19SBen Gras n0 = ((*(int*)&one)>>29)^1; * index of high word *
242fe8fb19SBen Gras ix0 = *(n0+(int*)&x); * high word of x *
252fe8fb19SBen Gras ix1 = *((1-n0)+(int*)&x); * low word of x *
262fe8fb19SBen Gras to dig two 32 bit words out of the 64 bit IEEE floating point
272fe8fb19SBen Gras value. That is non-ANSI, and, moreover, the gcc instruction
282fe8fb19SBen Gras scheduler gets it wrong. We instead use the following macros.
292fe8fb19SBen Gras Unlike the original code, we determine the endianness at compile
302fe8fb19SBen Gras time, not at run time; I don't see much benefit to selecting
312fe8fb19SBen Gras endianness at run time. */
322fe8fb19SBen Gras
332fe8fb19SBen Gras /* A union which permits us to convert between a double and two 32 bit
342fe8fb19SBen Gras ints. */
352fe8fb19SBen Gras
362fe8fb19SBen Gras /*
372fe8fb19SBen Gras * The ARM ports are little endian except for the FPA word order which is
382fe8fb19SBen Gras * big endian.
392fe8fb19SBen Gras */
402fe8fb19SBen Gras
412fe8fb19SBen Gras #if (BYTE_ORDER == BIG_ENDIAN) || (defined(__arm__) && !defined(__VFP_FP__))
422fe8fb19SBen Gras
432fe8fb19SBen Gras typedef union
442fe8fb19SBen Gras {
452fe8fb19SBen Gras double value;
462fe8fb19SBen Gras struct
472fe8fb19SBen Gras {
482fe8fb19SBen Gras u_int32_t msw;
492fe8fb19SBen Gras u_int32_t lsw;
502fe8fb19SBen Gras } parts;
5184d9c625SLionel Sambuc struct {
5284d9c625SLionel Sambuc u_int64_t w;
5384d9c625SLionel Sambuc } xparts;
542fe8fb19SBen Gras } ieee_double_shape_type;
552fe8fb19SBen Gras
562fe8fb19SBen Gras #endif
572fe8fb19SBen Gras
582fe8fb19SBen Gras #if (BYTE_ORDER == LITTLE_ENDIAN) && \
592fe8fb19SBen Gras !(defined(__arm__) && !defined(__VFP_FP__))
602fe8fb19SBen Gras
612fe8fb19SBen Gras typedef union
622fe8fb19SBen Gras {
632fe8fb19SBen Gras double value;
642fe8fb19SBen Gras struct
652fe8fb19SBen Gras {
662fe8fb19SBen Gras u_int32_t lsw;
672fe8fb19SBen Gras u_int32_t msw;
682fe8fb19SBen Gras } parts;
6984d9c625SLionel Sambuc struct {
7084d9c625SLionel Sambuc u_int64_t w;
7184d9c625SLionel Sambuc } xparts;
722fe8fb19SBen Gras } ieee_double_shape_type;
732fe8fb19SBen Gras
742fe8fb19SBen Gras #endif
752fe8fb19SBen Gras
762fe8fb19SBen Gras /* Get two 32 bit ints from a double. */
772fe8fb19SBen Gras
782fe8fb19SBen Gras #define EXTRACT_WORDS(ix0,ix1,d) \
792fe8fb19SBen Gras do { \
802fe8fb19SBen Gras ieee_double_shape_type ew_u; \
812fe8fb19SBen Gras ew_u.value = (d); \
822fe8fb19SBen Gras (ix0) = ew_u.parts.msw; \
832fe8fb19SBen Gras (ix1) = ew_u.parts.lsw; \
842fe8fb19SBen Gras } while (/*CONSTCOND*/0)
852fe8fb19SBen Gras
8684d9c625SLionel Sambuc /* Get a 64-bit int from a double. */
8784d9c625SLionel Sambuc #define EXTRACT_WORD64(ix,d) \
8884d9c625SLionel Sambuc do { \
8984d9c625SLionel Sambuc ieee_double_shape_type ew_u; \
9084d9c625SLionel Sambuc ew_u.value = (d); \
9184d9c625SLionel Sambuc (ix) = ew_u.xparts.w; \
9284d9c625SLionel Sambuc } while (/*CONSTCOND*/0)
9384d9c625SLionel Sambuc
9484d9c625SLionel Sambuc
952fe8fb19SBen Gras /* Get the more significant 32 bit int from a double. */
962fe8fb19SBen Gras
972fe8fb19SBen Gras #define GET_HIGH_WORD(i,d) \
982fe8fb19SBen Gras do { \
992fe8fb19SBen Gras ieee_double_shape_type gh_u; \
1002fe8fb19SBen Gras gh_u.value = (d); \
1012fe8fb19SBen Gras (i) = gh_u.parts.msw; \
1022fe8fb19SBen Gras } while (/*CONSTCOND*/0)
1032fe8fb19SBen Gras
1042fe8fb19SBen Gras /* Get the less significant 32 bit int from a double. */
1052fe8fb19SBen Gras
1062fe8fb19SBen Gras #define GET_LOW_WORD(i,d) \
1072fe8fb19SBen Gras do { \
1082fe8fb19SBen Gras ieee_double_shape_type gl_u; \
1092fe8fb19SBen Gras gl_u.value = (d); \
1102fe8fb19SBen Gras (i) = gl_u.parts.lsw; \
1112fe8fb19SBen Gras } while (/*CONSTCOND*/0)
1122fe8fb19SBen Gras
1132fe8fb19SBen Gras /* Set a double from two 32 bit ints. */
1142fe8fb19SBen Gras
1152fe8fb19SBen Gras #define INSERT_WORDS(d,ix0,ix1) \
1162fe8fb19SBen Gras do { \
1172fe8fb19SBen Gras ieee_double_shape_type iw_u; \
1182fe8fb19SBen Gras iw_u.parts.msw = (ix0); \
1192fe8fb19SBen Gras iw_u.parts.lsw = (ix1); \
1202fe8fb19SBen Gras (d) = iw_u.value; \
1212fe8fb19SBen Gras } while (/*CONSTCOND*/0)
1222fe8fb19SBen Gras
12384d9c625SLionel Sambuc /* Set a double from a 64-bit int. */
12484d9c625SLionel Sambuc #define INSERT_WORD64(d,ix) \
12584d9c625SLionel Sambuc do { \
12684d9c625SLionel Sambuc ieee_double_shape_type iw_u; \
12784d9c625SLionel Sambuc iw_u.xparts.w = (ix); \
12884d9c625SLionel Sambuc (d) = iw_u.value; \
12984d9c625SLionel Sambuc } while (/*CONSTCOND*/0)
13084d9c625SLionel Sambuc
13184d9c625SLionel Sambuc
1322fe8fb19SBen Gras /* Set the more significant 32 bits of a double from an int. */
1332fe8fb19SBen Gras
1342fe8fb19SBen Gras #define SET_HIGH_WORD(d,v) \
1352fe8fb19SBen Gras do { \
1362fe8fb19SBen Gras ieee_double_shape_type sh_u; \
1372fe8fb19SBen Gras sh_u.value = (d); \
1382fe8fb19SBen Gras sh_u.parts.msw = (v); \
1392fe8fb19SBen Gras (d) = sh_u.value; \
1402fe8fb19SBen Gras } while (/*CONSTCOND*/0)
1412fe8fb19SBen Gras
1422fe8fb19SBen Gras /* Set the less significant 32 bits of a double from an int. */
1432fe8fb19SBen Gras
1442fe8fb19SBen Gras #define SET_LOW_WORD(d,v) \
1452fe8fb19SBen Gras do { \
1462fe8fb19SBen Gras ieee_double_shape_type sl_u; \
1472fe8fb19SBen Gras sl_u.value = (d); \
1482fe8fb19SBen Gras sl_u.parts.lsw = (v); \
1492fe8fb19SBen Gras (d) = sl_u.value; \
1502fe8fb19SBen Gras } while (/*CONSTCOND*/0)
1512fe8fb19SBen Gras
1522fe8fb19SBen Gras /* A union which permits us to convert between a float and a 32 bit
1532fe8fb19SBen Gras int. */
1542fe8fb19SBen Gras
1552fe8fb19SBen Gras typedef union
1562fe8fb19SBen Gras {
1572fe8fb19SBen Gras float value;
1582fe8fb19SBen Gras u_int32_t word;
1592fe8fb19SBen Gras } ieee_float_shape_type;
1602fe8fb19SBen Gras
1612fe8fb19SBen Gras /* Get a 32 bit int from a float. */
1622fe8fb19SBen Gras
1632fe8fb19SBen Gras #define GET_FLOAT_WORD(i,d) \
1642fe8fb19SBen Gras do { \
1652fe8fb19SBen Gras ieee_float_shape_type gf_u; \
1662fe8fb19SBen Gras gf_u.value = (d); \
1672fe8fb19SBen Gras (i) = gf_u.word; \
1682fe8fb19SBen Gras } while (/*CONSTCOND*/0)
1692fe8fb19SBen Gras
1702fe8fb19SBen Gras /* Set a float from a 32 bit int. */
1712fe8fb19SBen Gras
1722fe8fb19SBen Gras #define SET_FLOAT_WORD(d,i) \
1732fe8fb19SBen Gras do { \
1742fe8fb19SBen Gras ieee_float_shape_type sf_u; \
1752fe8fb19SBen Gras sf_u.word = (i); \
1762fe8fb19SBen Gras (d) = sf_u.value; \
1772fe8fb19SBen Gras } while (/*CONSTCOND*/0)
1782fe8fb19SBen Gras
1792fe8fb19SBen Gras /*
1802fe8fb19SBen Gras * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
1812fe8fb19SBen Gras */
1822fe8fb19SBen Gras #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
1832fe8fb19SBen Gras #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
1842fe8fb19SBen Gras #else
1852fe8fb19SBen Gras #define STRICT_ASSIGN(type, lval, rval) do { \
1862fe8fb19SBen Gras volatile type __lval; \
1872fe8fb19SBen Gras \
188*0a6a1f1dSLionel Sambuc if (sizeof(type) >= sizeof(long double)) \
1892fe8fb19SBen Gras (lval) = (rval); \
1902fe8fb19SBen Gras else { \
1912fe8fb19SBen Gras __lval = (rval); \
1922fe8fb19SBen Gras (lval) = __lval; \
1932fe8fb19SBen Gras } \
1942fe8fb19SBen Gras } while (/*CONSTCOND*/0)
1952fe8fb19SBen Gras #endif
1962fe8fb19SBen Gras
1972fe8fb19SBen Gras #ifdef _COMPLEX_H
1982fe8fb19SBen Gras
1992fe8fb19SBen Gras /*
2002fe8fb19SBen Gras * Quoting from ISO/IEC 9899:TC2:
2012fe8fb19SBen Gras *
2022fe8fb19SBen Gras * 6.2.5.13 Types
2032fe8fb19SBen Gras * Each complex type has the same representation and alignment requirements as
2042fe8fb19SBen Gras * an array type containing exactly two elements of the corresponding real type;
2052fe8fb19SBen Gras * the first element is equal to the real part, and the second element to the
2062fe8fb19SBen Gras * imaginary part, of the complex number.
2072fe8fb19SBen Gras */
2082fe8fb19SBen Gras typedef union {
2092fe8fb19SBen Gras float complex z;
2102fe8fb19SBen Gras float parts[2];
2112fe8fb19SBen Gras } float_complex;
2122fe8fb19SBen Gras
2132fe8fb19SBen Gras typedef union {
2142fe8fb19SBen Gras double complex z;
2152fe8fb19SBen Gras double parts[2];
2162fe8fb19SBen Gras } double_complex;
2172fe8fb19SBen Gras
2182fe8fb19SBen Gras typedef union {
2192fe8fb19SBen Gras long double complex z;
2202fe8fb19SBen Gras long double parts[2];
2212fe8fb19SBen Gras } long_double_complex;
2222fe8fb19SBen Gras
2232fe8fb19SBen Gras #define REAL_PART(z) ((z).parts[0])
2242fe8fb19SBen Gras #define IMAG_PART(z) ((z).parts[1])
2252fe8fb19SBen Gras
2262fe8fb19SBen Gras #endif /* _COMPLEX_H */
2272fe8fb19SBen Gras
2282fe8fb19SBen Gras /* ieee style elementary functions */
2292fe8fb19SBen Gras extern double __ieee754_sqrt __P((double));
2302fe8fb19SBen Gras extern double __ieee754_acos __P((double));
2312fe8fb19SBen Gras extern double __ieee754_acosh __P((double));
2322fe8fb19SBen Gras extern double __ieee754_log __P((double));
2332fe8fb19SBen Gras extern double __ieee754_atanh __P((double));
2342fe8fb19SBen Gras extern double __ieee754_asin __P((double));
2352fe8fb19SBen Gras extern double __ieee754_atan2 __P((double,double));
2362fe8fb19SBen Gras extern double __ieee754_exp __P((double));
2372fe8fb19SBen Gras extern double __ieee754_cosh __P((double));
2382fe8fb19SBen Gras extern double __ieee754_fmod __P((double,double));
2392fe8fb19SBen Gras extern double __ieee754_pow __P((double,double));
2402fe8fb19SBen Gras extern double __ieee754_lgamma_r __P((double,int *));
2412fe8fb19SBen Gras extern double __ieee754_gamma_r __P((double,int *));
2422fe8fb19SBen Gras extern double __ieee754_lgamma __P((double));
2432fe8fb19SBen Gras extern double __ieee754_gamma __P((double));
2442fe8fb19SBen Gras extern double __ieee754_log10 __P((double));
2452fe8fb19SBen Gras extern double __ieee754_log2 __P((double));
2462fe8fb19SBen Gras extern double __ieee754_sinh __P((double));
2472fe8fb19SBen Gras extern double __ieee754_hypot __P((double,double));
2482fe8fb19SBen Gras extern double __ieee754_j0 __P((double));
2492fe8fb19SBen Gras extern double __ieee754_j1 __P((double));
2502fe8fb19SBen Gras extern double __ieee754_y0 __P((double));
2512fe8fb19SBen Gras extern double __ieee754_y1 __P((double));
2522fe8fb19SBen Gras extern double __ieee754_jn __P((int,double));
2532fe8fb19SBen Gras extern double __ieee754_yn __P((int,double));
2542fe8fb19SBen Gras extern double __ieee754_remainder __P((double,double));
255*0a6a1f1dSLionel Sambuc extern int32_t __ieee754_rem_pio2 __P((double,double*));
2562fe8fb19SBen Gras extern double __ieee754_scalb __P((double,double));
2572fe8fb19SBen Gras
2582fe8fb19SBen Gras /* fdlibm kernel function */
2592fe8fb19SBen Gras extern double __kernel_standard __P((double,double,int));
2602fe8fb19SBen Gras extern double __kernel_sin __P((double,double,int));
2612fe8fb19SBen Gras extern double __kernel_cos __P((double,double));
2622fe8fb19SBen Gras extern double __kernel_tan __P((double,double,int));
263*0a6a1f1dSLionel Sambuc extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const int32_t*));
2642fe8fb19SBen Gras
2652fe8fb19SBen Gras
2662fe8fb19SBen Gras /* ieee style elementary float functions */
2672fe8fb19SBen Gras extern float __ieee754_sqrtf __P((float));
2682fe8fb19SBen Gras extern float __ieee754_acosf __P((float));
2692fe8fb19SBen Gras extern float __ieee754_acoshf __P((float));
2702fe8fb19SBen Gras extern float __ieee754_logf __P((float));
2712fe8fb19SBen Gras extern float __ieee754_atanhf __P((float));
2722fe8fb19SBen Gras extern float __ieee754_asinf __P((float));
2732fe8fb19SBen Gras extern float __ieee754_atan2f __P((float,float));
2742fe8fb19SBen Gras extern float __ieee754_expf __P((float));
2752fe8fb19SBen Gras extern float __ieee754_coshf __P((float));
2762fe8fb19SBen Gras extern float __ieee754_fmodf __P((float,float));
2772fe8fb19SBen Gras extern float __ieee754_powf __P((float,float));
2782fe8fb19SBen Gras extern float __ieee754_lgammaf_r __P((float,int *));
2792fe8fb19SBen Gras extern float __ieee754_gammaf_r __P((float,int *));
2802fe8fb19SBen Gras extern float __ieee754_lgammaf __P((float));
2812fe8fb19SBen Gras extern float __ieee754_gammaf __P((float));
2822fe8fb19SBen Gras extern float __ieee754_log10f __P((float));
2832fe8fb19SBen Gras extern float __ieee754_log2f __P((float));
2842fe8fb19SBen Gras extern float __ieee754_sinhf __P((float));
2852fe8fb19SBen Gras extern float __ieee754_hypotf __P((float,float));
2862fe8fb19SBen Gras extern float __ieee754_j0f __P((float));
2872fe8fb19SBen Gras extern float __ieee754_j1f __P((float));
2882fe8fb19SBen Gras extern float __ieee754_y0f __P((float));
2892fe8fb19SBen Gras extern float __ieee754_y1f __P((float));
2902fe8fb19SBen Gras extern float __ieee754_jnf __P((int,float));
2912fe8fb19SBen Gras extern float __ieee754_ynf __P((int,float));
2922fe8fb19SBen Gras extern float __ieee754_remainderf __P((float,float));
293*0a6a1f1dSLionel Sambuc extern int32_t __ieee754_rem_pio2f __P((float,float*));
2942fe8fb19SBen Gras extern float __ieee754_scalbf __P((float,float));
2952fe8fb19SBen Gras
2962fe8fb19SBen Gras /* float versions of fdlibm kernel functions */
2972fe8fb19SBen Gras extern float __kernel_sinf __P((float,float,int));
2982fe8fb19SBen Gras extern float __kernel_cosf __P((float,float));
2992fe8fb19SBen Gras extern float __kernel_tanf __P((float,float,int));
300*0a6a1f1dSLionel Sambuc extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const int32_t*));
3012fe8fb19SBen Gras
30284d9c625SLionel Sambuc /* ieee style elementary long double functions */
30384d9c625SLionel Sambuc extern long double __ieee754_fmodl(long double, long double);
30484d9c625SLionel Sambuc extern long double __ieee754_sqrtl(long double);
30584d9c625SLionel Sambuc
30684d9c625SLionel Sambuc /*
30784d9c625SLionel Sambuc * TRUNC() is a macro that sets the trailing 27 bits in the mantissa of an
30884d9c625SLionel Sambuc * IEEE double variable to zero. It must be expression-like for syntactic
30984d9c625SLionel Sambuc * reasons, and we implement this expression using an inline function
31084d9c625SLionel Sambuc * instead of a pure macro to avoid depending on the gcc feature of
31184d9c625SLionel Sambuc * statement-expressions.
31284d9c625SLionel Sambuc */
31384d9c625SLionel Sambuc #define TRUNC(d) (_b_trunc(&(d)))
31484d9c625SLionel Sambuc
31584d9c625SLionel Sambuc static __inline void
_b_trunc(volatile double * _dp)31684d9c625SLionel Sambuc _b_trunc(volatile double *_dp)
31784d9c625SLionel Sambuc {
31884d9c625SLionel Sambuc uint32_t _lw;
31984d9c625SLionel Sambuc
32084d9c625SLionel Sambuc GET_LOW_WORD(_lw, *_dp);
32184d9c625SLionel Sambuc SET_LOW_WORD(*_dp, _lw & 0xf8000000);
32284d9c625SLionel Sambuc }
32384d9c625SLionel Sambuc
32484d9c625SLionel Sambuc struct Double {
32584d9c625SLionel Sambuc double a;
32684d9c625SLionel Sambuc double b;
32784d9c625SLionel Sambuc };
32884d9c625SLionel Sambuc
32984d9c625SLionel Sambuc /*
33084d9c625SLionel Sambuc * Functions internal to the math package, yet not static.
33184d9c625SLionel Sambuc */
33284d9c625SLionel Sambuc double __exp__D(double, double);
33384d9c625SLionel Sambuc struct Double __log__D(double);
33484d9c625SLionel Sambuc
3352fe8fb19SBen Gras #endif /* _MATH_PRIVATE_H_ */
336