Home | History | Annotate | Download | only in src
      1 /*
      2  * ====================================================
      3  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
      4  *
      5  * Developed at SunPro, a Sun Microsystems, Inc. business.
      6  * Permission to use, copy, modify, and distribute this
      7  * software is freely granted, provided that this notice
      8  * is preserved.
      9  * ====================================================
     10  */
     11 
     12 /*
     13  * from: @(#)fdlibm.h 5.1 93/09/24
     14  * $FreeBSD$
     15  */
     16 
     17 #ifndef _MATH_PRIVATE_H_
     18 #define	_MATH_PRIVATE_H_
     19 
     20 #include <sys/types.h>
     21 #include <machine/endian.h>
     22 
     23 /*
     24  * The original fdlibm code used statements like:
     25  *	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
     26  *	ix0 = *(n0+(int*)&x);			* high word of x *
     27  *	ix1 = *((1-n0)+(int*)&x);		* low word of x *
     28  * to dig two 32 bit words out of the 64 bit IEEE floating point
     29  * value.  That is non-ANSI, and, moreover, the gcc instruction
     30  * scheduler gets it wrong.  We instead use the following macros.
     31  * Unlike the original code, we determine the endianness at compile
     32  * time, not at run time; I don't see much benefit to selecting
     33  * endianness at run time.
     34  */
     35 
     36 /*
     37  * A union which permits us to convert between a double and two 32 bit
     38  * ints.
     39  */
     40 
     41 #ifdef __arm__
     42 #if defined(__VFP_FP__)
     43 #define	IEEE_WORD_ORDER	BYTE_ORDER
     44 #else
     45 #define	IEEE_WORD_ORDER	BIG_ENDIAN
     46 #endif
     47 #else /* __arm__ */
     48 #define	IEEE_WORD_ORDER	BYTE_ORDER
     49 #endif
     50 
     51 #if IEEE_WORD_ORDER == BIG_ENDIAN
     52 
     53 typedef union
     54 {
     55   double value;
     56   struct
     57   {
     58     u_int32_t msw;
     59     u_int32_t lsw;
     60   } parts;
     61   struct
     62   {
     63     u_int64_t w;
     64   } xparts;
     65 } ieee_double_shape_type;
     66 
     67 #endif
     68 
     69 #if IEEE_WORD_ORDER == LITTLE_ENDIAN
     70 
     71 typedef union
     72 {
     73   double value;
     74   struct
     75   {
     76     u_int32_t lsw;
     77     u_int32_t msw;
     78   } parts;
     79   struct
     80   {
     81     u_int64_t w;
     82   } xparts;
     83 } ieee_double_shape_type;
     84 
     85 #endif
     86 
     87 /* Get two 32 bit ints from a double.  */
     88 
     89 #define EXTRACT_WORDS(ix0,ix1,d)				\
     90 do {								\
     91   ieee_double_shape_type ew_u;					\
     92   ew_u.value = (d);						\
     93   (ix0) = ew_u.parts.msw;					\
     94   (ix1) = ew_u.parts.lsw;					\
     95 } while (0)
     96 
     97 /* Get a 64-bit int from a double. */
     98 #define EXTRACT_WORD64(ix,d)					\
     99 do {								\
    100   ieee_double_shape_type ew_u;					\
    101   ew_u.value = (d);						\
    102   (ix) = ew_u.xparts.w;						\
    103 } while (0)
    104 
    105 /* Get the more significant 32 bit int from a double.  */
    106 
    107 #define GET_HIGH_WORD(i,d)					\
    108 do {								\
    109   ieee_double_shape_type gh_u;					\
    110   gh_u.value = (d);						\
    111   (i) = gh_u.parts.msw;						\
    112 } while (0)
    113 
    114 /* Get the less significant 32 bit int from a double.  */
    115 
    116 #define GET_LOW_WORD(i,d)					\
    117 do {								\
    118   ieee_double_shape_type gl_u;					\
    119   gl_u.value = (d);						\
    120   (i) = gl_u.parts.lsw;						\
    121 } while (0)
    122 
    123 /* Set a double from two 32 bit ints.  */
    124 
    125 #define INSERT_WORDS(d,ix0,ix1)					\
    126 do {								\
    127   ieee_double_shape_type iw_u;					\
    128   iw_u.parts.msw = (ix0);					\
    129   iw_u.parts.lsw = (ix1);					\
    130   (d) = iw_u.value;						\
    131 } while (0)
    132 
    133 /* Set a double from a 64-bit int. */
    134 #define INSERT_WORD64(d,ix)					\
    135 do {								\
    136   ieee_double_shape_type iw_u;					\
    137   iw_u.xparts.w = (ix);						\
    138   (d) = iw_u.value;						\
    139 } while (0)
    140 
    141 /* Set the more significant 32 bits of a double from an int.  */
    142 
    143 #define SET_HIGH_WORD(d,v)					\
    144 do {								\
    145   ieee_double_shape_type sh_u;					\
    146   sh_u.value = (d);						\
    147   sh_u.parts.msw = (v);						\
    148   (d) = sh_u.value;						\
    149 } while (0)
    150 
    151 /* Set the less significant 32 bits of a double from an int.  */
    152 
    153 #define SET_LOW_WORD(d,v)					\
    154 do {								\
    155   ieee_double_shape_type sl_u;					\
    156   sl_u.value = (d);						\
    157   sl_u.parts.lsw = (v);						\
    158   (d) = sl_u.value;						\
    159 } while (0)
    160 
    161 /*
    162  * A union which permits us to convert between a float and a 32 bit
    163  * int.
    164  */
    165 
    166 typedef union
    167 {
    168   float value;
    169   /* FIXME: Assumes 32 bit int.  */
    170   unsigned int word;
    171 } ieee_float_shape_type;
    172 
    173 /* Get a 32 bit int from a float.  */
    174 
    175 #define GET_FLOAT_WORD(i,d)					\
    176 do {								\
    177   ieee_float_shape_type gf_u;					\
    178   gf_u.value = (d);						\
    179   (i) = gf_u.word;						\
    180 } while (0)
    181 
    182 /* Set a float from a 32 bit int.  */
    183 
    184 #define SET_FLOAT_WORD(d,i)					\
    185 do {								\
    186   ieee_float_shape_type sf_u;					\
    187   sf_u.word = (i);						\
    188   (d) = sf_u.value;						\
    189 } while (0)
    190 
    191 /* Get expsign as a 16 bit int from a long double.  */
    192 
    193 #define	GET_LDBL_EXPSIGN(i,d)					\
    194 do {								\
    195   union IEEEl2bits ge_u;					\
    196   ge_u.e = (d);							\
    197   (i) = ge_u.xbits.expsign;					\
    198 } while (0)
    199 
    200 /* Set expsign of a long double from a 16 bit int.  */
    201 
    202 #define	SET_LDBL_EXPSIGN(d,v)					\
    203 do {								\
    204   union IEEEl2bits se_u;					\
    205   se_u.e = (d);							\
    206   se_u.xbits.expsign = (v);					\
    207   (d) = se_u.e;							\
    208 } while (0)
    209 
    210 #ifdef __i386__
    211 /* Long double constants are broken on i386. */
    212 #define	LD80C(m, ex, v) {						\
    213 	.xbits.man = __CONCAT(m, ULL),					\
    214 	.xbits.expsign = (0x3fff + (ex)) | ((v) < 0 ? 0x8000 : 0),	\
    215 }
    216 #else
    217 /* The above works on non-i386 too, but we use this to check v. */
    218 #define	LD80C(m, ex, v)	{ .e = (v), }
    219 #endif
    220 
    221 #ifdef FLT_EVAL_METHOD
    222 /*
    223  * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
    224  */
    225 #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
    226 #define	STRICT_ASSIGN(type, lval, rval)	((lval) = (rval))
    227 #else
    228 #define	STRICT_ASSIGN(type, lval, rval) do {	\
    229 	volatile type __lval;			\
    230 						\
    231 	if (sizeof(type) >= sizeof(long double))	\
    232 		(lval) = (rval);		\
    233 	else {					\
    234 		__lval = (rval);		\
    235 		(lval) = __lval;		\
    236 	}					\
    237 } while (0)
    238 #endif
    239 #endif /* FLT_EVAL_METHOD */
    240 
    241 /* Support switching the mode to FP_PE if necessary. */
    242 #if defined(__i386__) && !defined(NO_FPSETPREC)
    243 #define	ENTERI()				\
    244 	long double __retval;			\
    245 	fp_prec_t __oprec;			\
    246 						\
    247 	if ((__oprec = fpgetprec()) != FP_PE)	\
    248 		fpsetprec(FP_PE)
    249 #define	RETURNI(x) do {				\
    250 	__retval = (x);				\
    251 	if (__oprec != FP_PE)			\
    252 		fpsetprec(__oprec);		\
    253 	RETURNF(__retval);			\
    254 } while (0)
    255 #else
    256 #define	ENTERI(x)
    257 #define	RETURNI(x)	RETURNF(x)
    258 #endif
    259 
    260 /* Default return statement if hack*_t() is not used. */
    261 #define      RETURNF(v)      return (v)
    262 
    263 /*
    264  * Common routine to process the arguments to nan(), nanf(), and nanl().
    265  */
    266 void _scan_nan(uint32_t *__words, int __num_words, const char *__s);
    267 
    268 #ifdef _COMPLEX_H
    269 
    270 /*
    271  * C99 specifies that complex numbers have the same representation as
    272  * an array of two elements, where the first element is the real part
    273  * and the second element is the imaginary part.
    274  */
    275 typedef union {
    276 	float complex f;
    277 	float a[2];
    278 } float_complex;
    279 typedef union {
    280 	double complex f;
    281 	double a[2];
    282 } double_complex;
    283 typedef union {
    284 	long double complex f;
    285 	long double a[2];
    286 } long_double_complex;
    287 #define	REALPART(z)	((z).a[0])
    288 #define	IMAGPART(z)	((z).a[1])
    289 
    290 /*
    291  * Inline functions that can be used to construct complex values.
    292  *
    293  * The C99 standard intends x+I*y to be used for this, but x+I*y is
    294  * currently unusable in general since gcc introduces many overflow,
    295  * underflow, sign and efficiency bugs by rewriting I*y as
    296  * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product.
    297  * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted
    298  * to -0.0+I*0.0.
    299  */
    300 static __inline float complex
    301 cpackf(float x, float y)
    302 {
    303 	float_complex z;
    304 
    305 	REALPART(z) = x;
    306 	IMAGPART(z) = y;
    307 	return (z.f);
    308 }
    309 
    310 static __inline double complex
    311 cpack(double x, double y)
    312 {
    313 	double_complex z;
    314 
    315 	REALPART(z) = x;
    316 	IMAGPART(z) = y;
    317 	return (z.f);
    318 }
    319 
    320 static __inline long double complex
    321 cpackl(long double x, long double y)
    322 {
    323 	long_double_complex z;
    324 
    325 	REALPART(z) = x;
    326 	IMAGPART(z) = y;
    327 	return (z.f);
    328 }
    329 #endif /* _COMPLEX_H */
    330 
    331 #ifdef __GNUCLIKE_ASM
    332 
    333 /* Asm versions of some functions. */
    334 
    335 #ifdef __amd64__
    336 static __inline int
    337 irint(double x)
    338 {
    339 	int n;
    340 
    341 	asm("cvtsd2si %1,%0" : "=r" (n) : "x" (x));
    342 	return (n);
    343 }
    344 #define	HAVE_EFFICIENT_IRINT
    345 #endif
    346 
    347 #ifdef __i386__
    348 static __inline int
    349 irint(double x)
    350 {
    351 	int n;
    352 
    353 	asm("fistl %0" : "=m" (n) : "t" (x));
    354 	return (n);
    355 }
    356 #define	HAVE_EFFICIENT_IRINT
    357 #endif
    358 
    359 #if defined(__amd64__) || defined(__i386__)
    360 static __inline int
    361 irintl(long double x)
    362 {
    363 	int n;
    364 
    365 	asm("fistl %0" : "=m" (n) : "t" (x));
    366 	return (n);
    367 }
    368 #define	HAVE_EFFICIENT_IRINTL
    369 #endif
    370 
    371 #endif /* __GNUCLIKE_ASM */
    372 
    373 /*
    374  * ieee style elementary functions
    375  *
    376  * We rename functions here to improve other sources' diffability
    377  * against fdlibm.
    378  */
    379 #define	__ieee754_sqrt	sqrt
    380 #define	__ieee754_acos	acos
    381 #define	__ieee754_acosh	acosh
    382 #define	__ieee754_log	log
    383 #define	__ieee754_log2	log2
    384 #define	__ieee754_atanh	atanh
    385 #define	__ieee754_asin	asin
    386 #define	__ieee754_atan2	atan2
    387 #define	__ieee754_exp	exp
    388 #define	__ieee754_cosh	cosh
    389 #define	__ieee754_fmod	fmod
    390 #define	__ieee754_pow	pow
    391 #define	__ieee754_lgamma lgamma
    392 #define	__ieee754_gamma	gamma
    393 #define	__ieee754_lgamma_r lgamma_r
    394 #define	__ieee754_gamma_r gamma_r
    395 #define	__ieee754_log10	log10
    396 #define	__ieee754_sinh	sinh
    397 #define	__ieee754_hypot	hypot
    398 #define	__ieee754_j0	j0
    399 #define	__ieee754_j1	j1
    400 #define	__ieee754_y0	y0
    401 #define	__ieee754_y1	y1
    402 #define	__ieee754_jn	jn
    403 #define	__ieee754_yn	yn
    404 #define	__ieee754_remainder remainder
    405 #define	__ieee754_scalb	scalb
    406 #define	__ieee754_sqrtf	sqrtf
    407 #define	__ieee754_acosf	acosf
    408 #define	__ieee754_acoshf acoshf
    409 #define	__ieee754_logf	logf
    410 #define	__ieee754_atanhf atanhf
    411 #define	__ieee754_asinf	asinf
    412 #define	__ieee754_atan2f atan2f
    413 #define	__ieee754_expf	expf
    414 #define	__ieee754_coshf	coshf
    415 #define	__ieee754_fmodf	fmodf
    416 #define	__ieee754_powf	powf
    417 #define	__ieee754_lgammaf lgammaf
    418 #define	__ieee754_gammaf gammaf
    419 #define	__ieee754_lgammaf_r lgammaf_r
    420 #define	__ieee754_gammaf_r gammaf_r
    421 #define	__ieee754_log10f log10f
    422 #define	__ieee754_log2f log2f
    423 #define	__ieee754_sinhf	sinhf
    424 #define	__ieee754_hypotf hypotf
    425 #define	__ieee754_j0f	j0f
    426 #define	__ieee754_j1f	j1f
    427 #define	__ieee754_y0f	y0f
    428 #define	__ieee754_y1f	y1f
    429 #define	__ieee754_jnf	jnf
    430 #define	__ieee754_ynf	ynf
    431 #define	__ieee754_remainderf remainderf
    432 #define	__ieee754_scalbf scalbf
    433 
    434 /* fdlibm kernel function */
    435 int	__kernel_rem_pio2(double*,double*,int,int,int);
    436 
    437 /* double precision kernel functions */
    438 #ifndef INLINE_REM_PIO2
    439 int	__ieee754_rem_pio2(double,double*);
    440 #endif
    441 double	__kernel_sin(double,double,int);
    442 double	__kernel_cos(double,double);
    443 double	__kernel_tan(double,double,int);
    444 double	__ldexp_exp(double,int);
    445 #ifdef _COMPLEX_H
    446 double complex __ldexp_cexp(double complex,int);
    447 #endif
    448 
    449 /* float precision kernel functions */
    450 #ifndef INLINE_REM_PIO2F
    451 int	__ieee754_rem_pio2f(float,double*);
    452 #endif
    453 #ifndef INLINE_KERNEL_SINDF
    454 float	__kernel_sindf(double);
    455 #endif
    456 #ifndef INLINE_KERNEL_COSDF
    457 float	__kernel_cosdf(double);
    458 #endif
    459 #ifndef INLINE_KERNEL_TANDF
    460 float	__kernel_tandf(double,int);
    461 #endif
    462 float	__ldexp_expf(float,int);
    463 #ifdef _COMPLEX_H
    464 float complex __ldexp_cexpf(float complex,int);
    465 #endif
    466 
    467 /* long double precision kernel functions */
    468 long double __kernel_sinl(long double, long double, int);
    469 long double __kernel_cosl(long double, long double);
    470 long double __kernel_tanl(long double, long double, int);
    471 
    472 #endif /* !_MATH_PRIVATE_H_ */
    473