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: src/lib/msun/src/math_private.h,v 1.34 2011/10/21 06:27:56 das Exp $ 15 */ 16 17 #ifndef _MATH_PRIVATE_H_ 18 #define _MATH_PRIVATE_H_ 19 20 #include <openlibm_complex.h> 21 22 #include "cdefs-compat.h" 23 #include "types-compat.h" 24 #include "fpmath.h" 25 #include <stdint.h> 26 #include "math_private_openbsd.h" 27 28 /* 29 * The original fdlibm code used statements like: 30 * n0 = ((*(int*)&one)>>29)^1; * index of high word * 31 * ix0 = *(n0+(int*)&x); * high word of x * 32 * ix1 = *((1-n0)+(int*)&x); * low word of x * 33 * to dig two 32 bit words out of the 64 bit IEEE floating point 34 * value. That is non-ANSI, and, moreover, the gcc instruction 35 * scheduler gets it wrong. We instead use the following macros. 36 * Unlike the original code, we determine the endianness at compile 37 * time, not at run time; I don't see much benefit to selecting 38 * endianness at run time. 39 */ 40 41 /* 42 * A union which permits us to convert between a double and two 32 bit 43 * ints. 44 */ 45 46 #if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__ 47 48 typedef union 49 { 50 double value; 51 struct 52 { 53 u_int32_t msw; 54 u_int32_t lsw; 55 } parts; 56 struct 57 { 58 u_int64_t w; 59 } xparts; 60 } ieee_double_shape_type; 61 62 #endif 63 64 #if __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__ 65 66 typedef union 67 { 68 double value; 69 struct 70 { 71 u_int32_t lsw; 72 u_int32_t msw; 73 } parts; 74 struct 75 { 76 u_int64_t w; 77 } xparts; 78 } ieee_double_shape_type; 79 80 #endif 81 82 /* Get two 32 bit ints from a double. */ 83 84 #define EXTRACT_WORDS(ix0,ix1,d) \ 85 do { \ 86 ieee_double_shape_type ew_u; \ 87 ew_u.value = (d); \ 88 (ix0) = ew_u.parts.msw; \ 89 (ix1) = ew_u.parts.lsw; \ 90 } while (0) 91 92 /* Get a 64-bit int from a double. */ 93 #define EXTRACT_WORD64(ix,d) \ 94 do { \ 95 ieee_double_shape_type ew_u; \ 96 ew_u.value = (d); \ 97 (ix) = ew_u.xparts.w; \ 98 } while (0) 99 100 /* Get the more significant 32 bit int from a double. */ 101 102 #define GET_HIGH_WORD(i,d) \ 103 do { \ 104 ieee_double_shape_type gh_u; \ 105 gh_u.value = (d); \ 106 (i) = gh_u.parts.msw; \ 107 } while (0) 108 109 /* Get the less significant 32 bit int from a double. */ 110 111 #define GET_LOW_WORD(i,d) \ 112 do { \ 113 ieee_double_shape_type gl_u; \ 114 gl_u.value = (d); \ 115 (i) = gl_u.parts.lsw; \ 116 } while (0) 117 118 /* Set a double from two 32 bit ints. */ 119 120 #define INSERT_WORDS(d,ix0,ix1) \ 121 do { \ 122 ieee_double_shape_type iw_u; \ 123 iw_u.parts.msw = (ix0); \ 124 iw_u.parts.lsw = (ix1); \ 125 (d) = iw_u.value; \ 126 } while (0) 127 128 /* Set a double from a 64-bit int. */ 129 #define INSERT_WORD64(d,ix) \ 130 do { \ 131 ieee_double_shape_type iw_u; \ 132 iw_u.xparts.w = (ix); \ 133 (d) = iw_u.value; \ 134 } while (0) 135 136 /* Set the more significant 32 bits of a double from an int. */ 137 138 #define SET_HIGH_WORD(d,v) \ 139 do { \ 140 ieee_double_shape_type sh_u; \ 141 sh_u.value = (d); \ 142 sh_u.parts.msw = (v); \ 143 (d) = sh_u.value; \ 144 } while (0) 145 146 /* Set the less significant 32 bits of a double from an int. */ 147 148 #define SET_LOW_WORD(d,v) \ 149 do { \ 150 ieee_double_shape_type sl_u; \ 151 sl_u.value = (d); \ 152 sl_u.parts.lsw = (v); \ 153 (d) = sl_u.value; \ 154 } while (0) 155 156 /* 157 * A union which permits us to convert between a float and a 32 bit 158 * int. 159 */ 160 161 typedef union 162 { 163 float value; 164 /* FIXME: Assumes 32 bit int. */ 165 unsigned int word; 166 } ieee_float_shape_type; 167 168 /* Get a 32 bit int from a float. */ 169 170 #define GET_FLOAT_WORD(i,d) \ 171 do { \ 172 ieee_float_shape_type gf_u; \ 173 gf_u.value = (d); \ 174 (i) = gf_u.word; \ 175 } while (0) 176 177 /* Set a float from a 32 bit int. */ 178 179 #define SET_FLOAT_WORD(d,i) \ 180 do { \ 181 ieee_float_shape_type sf_u; \ 182 sf_u.word = (i); \ 183 (d) = sf_u.value; \ 184 } while (0) 185 186 /* Get expsign as a 16 bit int from a long double. */ 187 188 #define GET_LDBL_EXPSIGN(i,d) \ 189 do { \ 190 union IEEEl2bits ge_u; \ 191 ge_u.e = (d); \ 192 (i) = ge_u.xbits.expsign; \ 193 } while (0) 194 195 /* Set expsign of a long double from a 16 bit int. */ 196 197 #define SET_LDBL_EXPSIGN(d,v) \ 198 do { \ 199 union IEEEl2bits se_u; \ 200 se_u.e = (d); \ 201 se_u.xbits.expsign = (v); \ 202 (d) = se_u.e; \ 203 } while (0) 204 205 206 //VBS 207 #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval)) 208 209 /* VBS 210 #ifdef FLT_EVAL_METHOD 211 // Attempt to get strict C99 semantics for assignment with non-C99 compilers. 212 #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0 213 #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval)) 214 #else 215 #define STRICT_ASSIGN(type, lval, rval) do { \ 216 volatile type __lval; \ 217 \ 218 if (sizeof(type) >= sizeof(double)) \ 219 (lval) = (rval); \ 220 else { \ 221 __lval = (rval); \ 222 (lval) = __lval; \ 223 } \ 224 } while (0) 225 #endif 226 #endif 227 */ 228 229 /* 230 * Common routine to process the arguments to nan(), nanf(), and nanl(). 231 */ 232 void __scan_nan(u_int32_t *__words, int __num_words, const char *__s); 233 234 #ifdef __GNUCLIKE_ASM 235 236 /* Asm versions of some functions. */ 237 238 #ifdef __amd64__ 239 static __inline int 240 irint(double x) 241 { 242 int n; 243 244 __asm__("cvtsd2si %1,%0" : "=r" (n) : "x" (x)); 245 return (n); 246 } 247 #define HAVE_EFFICIENT_IRINT 248 #endif 249 250 #ifdef __i386__ 251 static __inline int 252 irint(double x) 253 { 254 int n; 255 256 __asm__("fistl %0" : "=m" (n) : "t" (x)); 257 return (n); 258 } 259 #define HAVE_EFFICIENT_IRINT 260 #endif 261 262 #endif /* __GNUCLIKE_ASM */ 263 264 /* 265 * ieee style elementary functions 266 * 267 * We rename functions here to improve other sources' diffability 268 * against fdlibm. 269 */ 270 #define __ieee754_sqrt sqrt 271 #define __ieee754_acos acos 272 #define __ieee754_acosh acosh 273 #define __ieee754_log log 274 #define __ieee754_log2 log2 275 #define __ieee754_atanh atanh 276 #define __ieee754_asin asin 277 #define __ieee754_atan2 atan2 278 #define __ieee754_exp exp 279 #define __ieee754_cosh cosh 280 #define __ieee754_fmod fmod 281 #define __ieee754_pow pow 282 #define __ieee754_lgamma lgamma 283 #define __ieee754_lgamma_r lgamma_r 284 #define __ieee754_log10 log10 285 #define __ieee754_sinh sinh 286 #define __ieee754_hypot hypot 287 #define __ieee754_j0 j0 288 #define __ieee754_j1 j1 289 #define __ieee754_y0 y0 290 #define __ieee754_y1 y1 291 #define __ieee754_jn jn 292 #define __ieee754_yn yn 293 #define __ieee754_remainder remainder 294 #define __ieee754_sqrtf sqrtf 295 #define __ieee754_acosf acosf 296 #define __ieee754_acoshf acoshf 297 #define __ieee754_logf logf 298 #define __ieee754_atanhf atanhf 299 #define __ieee754_asinf asinf 300 #define __ieee754_atan2f atan2f 301 #define __ieee754_expf expf 302 #define __ieee754_coshf coshf 303 #define __ieee754_fmodf fmodf 304 #define __ieee754_powf powf 305 #define __ieee754_lgammaf lgammaf 306 #define __ieee754_lgammaf_r lgammaf_r 307 #define __ieee754_log10f log10f 308 #define __ieee754_log2f log2f 309 #define __ieee754_sinhf sinhf 310 #define __ieee754_hypotf hypotf 311 #define __ieee754_j0f j0f 312 #define __ieee754_j1f j1f 313 #define __ieee754_y0f y0f 314 #define __ieee754_y1f y1f 315 #define __ieee754_jnf jnf 316 #define __ieee754_ynf ynf 317 #define __ieee754_remainderf remainderf 318 319 /* fdlibm kernel function */ 320 int __kernel_rem_pio2(double*,double*,int,int,int); 321 322 /* double precision kernel functions */ 323 #ifdef INLINE_REM_PIO2 324 __inline 325 #endif 326 int __ieee754_rem_pio2(double,double*); 327 double __kernel_sin(double,double,int); 328 double __kernel_cos(double,double); 329 double __kernel_tan(double,double,int); 330 double __ldexp_exp(double,int); 331 double complex __ldexp_cexp(double complex,int); 332 333 /* float precision kernel functions */ 334 #ifdef INLINE_REM_PIO2F 335 __inline 336 #endif 337 int __ieee754_rem_pio2f(float,double*); 338 #ifdef INLINE_KERNEL_SINDF 339 __inline 340 #endif 341 float __kernel_sindf(double); 342 #ifdef INLINE_KERNEL_COSDF 343 __inline 344 #endif 345 float __kernel_cosdf(double); 346 #ifdef INLINE_KERNEL_TANDF 347 __inline 348 #endif 349 float __kernel_tandf(double,int); 350 float __ldexp_expf(float,int); 351 float complex __ldexp_cexpf(float complex,int); 352 353 /* long double precision kernel functions */ 354 long double __kernel_sinl(long double, long double, int); 355 long double __kernel_cosl(long double, long double); 356 long double __kernel_tanl(long double, long double, int); 357 358 #undef OLM_DLLEXPORT 359 #ifdef _WIN32 360 # ifdef IMPORT_EXPORTS 361 # define OLM_DLLEXPORT __declspec(dllimport) 362 # else 363 # define OLM_DLLEXPORT __declspec(OLM_DLLEXPORT) 364 # endif 365 #else 366 #define OLM_DLLEXPORT __attribute__ ((visibility("default"))) 367 #endif 368 369 370 #endif /* !_MATH_PRIVATE_H_ */ 371