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 #if BYTE_ORDER == BIG_ENDIAN 42 43 typedef union 44 { 45 double value; 46 struct 47 { 48 u_int32_t msw; 49 u_int32_t lsw; 50 } parts; 51 } ieee_double_shape_type; 52 53 #endif 54 55 #if BYTE_ORDER == LITTLE_ENDIAN 56 57 typedef union 58 { 59 double value; 60 struct 61 { 62 u_int32_t lsw; 63 u_int32_t msw; 64 } parts; 65 } ieee_double_shape_type; 66 67 #endif 68 69 /* Get two 32 bit ints from a double. */ 70 71 #define EXTRACT_WORDS(ix0,ix1,d) \ 72 do { \ 73 ieee_double_shape_type ew_u; \ 74 ew_u.value = (d); \ 75 (ix0) = ew_u.parts.msw; \ 76 (ix1) = ew_u.parts.lsw; \ 77 } while (0) 78 79 /* Get the more significant 32 bit int from a double. */ 80 81 #define GET_HIGH_WORD(i,d) \ 82 do { \ 83 ieee_double_shape_type gh_u; \ 84 gh_u.value = (d); \ 85 (i) = gh_u.parts.msw; \ 86 } while (0) 87 88 /* Get the less significant 32 bit int from a double. */ 89 90 #define GET_LOW_WORD(i,d) \ 91 do { \ 92 ieee_double_shape_type gl_u; \ 93 gl_u.value = (d); \ 94 (i) = gl_u.parts.lsw; \ 95 } while (0) 96 97 /* Set a double from two 32 bit ints. */ 98 99 #define INSERT_WORDS(d,ix0,ix1) \ 100 do { \ 101 ieee_double_shape_type iw_u; \ 102 iw_u.parts.msw = (ix0); \ 103 iw_u.parts.lsw = (ix1); \ 104 (d) = iw_u.value; \ 105 } while (0) 106 107 /* Set the more significant 32 bits of a double from an int. */ 108 109 #define SET_HIGH_WORD(d,v) \ 110 do { \ 111 ieee_double_shape_type sh_u; \ 112 sh_u.value = (d); \ 113 sh_u.parts.msw = (v); \ 114 (d) = sh_u.value; \ 115 } while (0) 116 117 /* Set the less significant 32 bits of a double from an int. */ 118 119 #define SET_LOW_WORD(d,v) \ 120 do { \ 121 ieee_double_shape_type sl_u; \ 122 sl_u.value = (d); \ 123 sl_u.parts.lsw = (v); \ 124 (d) = sl_u.value; \ 125 } while (0) 126 127 /* 128 * A union which permits us to convert between a float and a 32 bit 129 * int. 130 */ 131 132 typedef union 133 { 134 float value; 135 /* FIXME: Assumes 32 bit int. */ 136 unsigned int word; 137 } ieee_float_shape_type; 138 139 /* Get a 32 bit int from a float. */ 140 141 #define GET_FLOAT_WORD(i,d) \ 142 do { \ 143 ieee_float_shape_type gf_u; \ 144 gf_u.value = (d); \ 145 (i) = gf_u.word; \ 146 } while (0) 147 148 /* Set a float from a 32 bit int. */ 149 150 #define SET_FLOAT_WORD(d,i) \ 151 do { \ 152 ieee_float_shape_type sf_u; \ 153 sf_u.word = (i); \ 154 (d) = sf_u.value; \ 155 } while (0) 156 157 /* 158 * Common routine to process the arguments to nan(), nanf(), and nanl(). 159 */ 160 void _scan_nan(uint32_t *__words, int __num_words, const char *__s); 161 162 #ifdef _COMPLEX_H 163 /* 164 * Inline functions that can be used to construct complex values. 165 * 166 * The C99 standard intends x+I*y to be used for this, but x+I*y is 167 * currently unusable in general since gcc introduces many overflow, 168 * underflow, sign and efficiency bugs by rewriting I*y as 169 * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product. 170 * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted 171 * to -0.0+I*0.0. 172 */ 173 static __inline float complex 174 cpackf(float x, float y) 175 { 176 float complex z; 177 178 __real__ z = x; 179 __imag__ z = y; 180 return (z); 181 } 182 183 static __inline double complex 184 cpack(double x, double y) 185 { 186 double complex z; 187 188 __real__ z = x; 189 __imag__ z = y; 190 return (z); 191 } 192 193 static __inline long double complex 194 cpackl(long double x, long double y) 195 { 196 long double complex z; 197 198 __real__ z = x; 199 __imag__ z = y; 200 return (z); 201 } 202 #endif /* _COMPLEX_H */ 203 204 /* 205 * ieee style elementary functions 206 * 207 * We rename functions here to improve other sources' diffability 208 * against fdlibm. 209 */ 210 #define __ieee754_sqrt sqrt 211 #define __ieee754_acos acos 212 #define __ieee754_acosh acosh 213 #define __ieee754_log log 214 #define __ieee754_atanh atanh 215 #define __ieee754_asin asin 216 #define __ieee754_atan2 atan2 217 #define __ieee754_exp exp 218 #define __ieee754_cosh cosh 219 #define __ieee754_fmod fmod 220 #define __ieee754_pow pow 221 #define __ieee754_lgamma lgamma 222 #define __ieee754_gamma gamma 223 #define __ieee754_lgamma_r lgamma_r 224 #define __ieee754_gamma_r gamma_r 225 #define __ieee754_log10 log10 226 #define __ieee754_sinh sinh 227 #define __ieee754_hypot hypot 228 #define __ieee754_j0 j0 229 #define __ieee754_j1 j1 230 #define __ieee754_y0 y0 231 #define __ieee754_y1 y1 232 #define __ieee754_jn jn 233 #define __ieee754_yn yn 234 #define __ieee754_remainder remainder 235 #define __ieee754_scalb scalb 236 #define __ieee754_sqrtf sqrtf 237 #define __ieee754_acosf acosf 238 #define __ieee754_acoshf acoshf 239 #define __ieee754_logf logf 240 #define __ieee754_atanhf atanhf 241 #define __ieee754_asinf asinf 242 #define __ieee754_atan2f atan2f 243 #define __ieee754_expf expf 244 #define __ieee754_coshf coshf 245 #define __ieee754_fmodf fmodf 246 #define __ieee754_powf powf 247 #define __ieee754_lgammaf lgammaf 248 #define __ieee754_gammaf gammaf 249 #define __ieee754_lgammaf_r lgammaf_r 250 #define __ieee754_gammaf_r gammaf_r 251 #define __ieee754_log10f log10f 252 #define __ieee754_sinhf sinhf 253 #define __ieee754_hypotf hypotf 254 #define __ieee754_j0f j0f 255 #define __ieee754_j1f j1f 256 #define __ieee754_y0f y0f 257 #define __ieee754_y1f y1f 258 #define __ieee754_jnf jnf 259 #define __ieee754_ynf ynf 260 #define __ieee754_remainderf remainderf 261 #define __ieee754_scalbf scalbf 262 263 /* fdlibm kernel function */ 264 int __ieee754_rem_pio2(double,double*); 265 double __kernel_sin(double,double,int); 266 double __kernel_cos(double,double); 267 double __kernel_tan(double,double,int); 268 int __kernel_rem_pio2(double*,double*,int,int,int,const int*); 269 270 /* float versions of fdlibm kernel functions */ 271 int __ieee754_rem_pio2f(float,float*); 272 float __kernel_sindf(double); 273 float __kernel_cosdf(double); 274 float __kernel_tandf(double,int); 275 int __kernel_rem_pio2f(float*,float*,int,int,int,const int*); 276 277 #endif /* !_MATH_PRIVATE_H_ */ 278