xref: /minix3/lib/libm/src/math_private.h (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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