1 /* $OpenBSD: math_private.h,v 1.18 2016/09/12 19:47:02 guenther Exp $ */ 2 /* 3 * ==================================================== 4 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5 * 6 * Developed at SunPro, a Sun Microsystems, Inc. business. 7 * Permission to use, copy, modify, and distribute this 8 * software is freely granted, provided that this notice 9 * is preserved. 10 * ==================================================== 11 */ 12 13 /* 14 * from: @(#)fdlibm.h 5.1 93/09/24 15 */ 16 17 #ifndef _MATH_PRIVATE_H_ 18 #define _MATH_PRIVATE_H_ 19 20 #include <sys/types.h> 21 22 /* The original fdlibm code used statements like: 23 n0 = ((*(int*)&one)>>29)^1; * index of high word * 24 ix0 = *(n0+(int*)&x); * high word of x * 25 ix1 = *((1-n0)+(int*)&x); * low word of x * 26 to dig two 32 bit words out of the 64 bit IEEE floating point 27 value. That is non-ANSI, and, moreover, the gcc instruction 28 scheduler gets it wrong. We instead use the following macros. 29 Unlike the original code, we determine the endianness at compile 30 time, not at run time; I don't see much benefit to selecting 31 endianness at run time. */ 32 33 /* A union which permits us to convert between a long double and 34 four 32 bit ints. */ 35 36 #if BYTE_ORDER == BIG_ENDIAN 37 38 typedef union 39 { 40 long double value; 41 struct { 42 u_int32_t mswhi; 43 u_int32_t mswlo; 44 u_int32_t lswhi; 45 u_int32_t lswlo; 46 } parts32; 47 struct { 48 u_int64_t msw; 49 u_int64_t lsw; 50 } parts64; 51 } ieee_quad_shape_type; 52 53 #endif 54 55 #if BYTE_ORDER == LITTLE_ENDIAN 56 57 typedef union 58 { 59 long double value; 60 struct { 61 u_int32_t lswlo; 62 u_int32_t lswhi; 63 u_int32_t mswlo; 64 u_int32_t mswhi; 65 } parts32; 66 struct { 67 u_int64_t lsw; 68 u_int64_t msw; 69 } parts64; 70 } ieee_quad_shape_type; 71 72 #endif 73 74 /* Get two 64 bit ints from a long double. */ 75 76 #define GET_LDOUBLE_WORDS64(ix0,ix1,d) \ 77 do { \ 78 ieee_quad_shape_type qw_u; \ 79 qw_u.value = (d); \ 80 (ix0) = qw_u.parts64.msw; \ 81 (ix1) = qw_u.parts64.lsw; \ 82 } while (0) 83 84 /* Set a long double from two 64 bit ints. */ 85 86 #define SET_LDOUBLE_WORDS64(d,ix0,ix1) \ 87 do { \ 88 ieee_quad_shape_type qw_u; \ 89 qw_u.parts64.msw = (ix0); \ 90 qw_u.parts64.lsw = (ix1); \ 91 (d) = qw_u.value; \ 92 } while (0) 93 94 /* Get the more significant 64 bits of a long double mantissa. */ 95 96 #define GET_LDOUBLE_MSW64(v,d) \ 97 do { \ 98 ieee_quad_shape_type sh_u; \ 99 sh_u.value = (d); \ 100 (v) = sh_u.parts64.msw; \ 101 } while (0) 102 103 /* Set the more significant 64 bits of a long double mantissa from an int. */ 104 105 #define SET_LDOUBLE_MSW64(d,v) \ 106 do { \ 107 ieee_quad_shape_type sh_u; \ 108 sh_u.value = (d); \ 109 sh_u.parts64.msw = (v); \ 110 (d) = sh_u.value; \ 111 } while (0) 112 113 /* Get the least significant 64 bits of a long double mantissa. */ 114 115 #define GET_LDOUBLE_LSW64(v,d) \ 116 do { \ 117 ieee_quad_shape_type sh_u; \ 118 sh_u.value = (d); \ 119 (v) = sh_u.parts64.lsw; \ 120 } while (0) 121 122 /* A union which permits us to convert between a long double and 123 three 32 bit ints. */ 124 125 #if BYTE_ORDER == BIG_ENDIAN 126 127 typedef union 128 { 129 long double value; 130 struct { 131 #ifdef __LP64__ 132 int padh:32; 133 #endif 134 int exp:16; 135 int padl:16; 136 u_int32_t msw; 137 u_int32_t lsw; 138 } parts; 139 } ieee_extended_shape_type; 140 141 #endif 142 143 #if BYTE_ORDER == LITTLE_ENDIAN 144 145 typedef union 146 { 147 long double value; 148 struct { 149 u_int32_t lsw; 150 u_int32_t msw; 151 int exp:16; 152 int padl:16; 153 #ifdef __LP64__ 154 int padh:32; 155 #endif 156 } parts; 157 } ieee_extended_shape_type; 158 159 #endif 160 161 /* Get three 32 bit ints from a double. */ 162 163 #define GET_LDOUBLE_WORDS(se,ix0,ix1,d) \ 164 do { \ 165 ieee_extended_shape_type ew_u; \ 166 ew_u.value = (d); \ 167 (se) = ew_u.parts.exp; \ 168 (ix0) = ew_u.parts.msw; \ 169 (ix1) = ew_u.parts.lsw; \ 170 } while (0) 171 172 /* Set a double from two 32 bit ints. */ 173 174 #define SET_LDOUBLE_WORDS(d,se,ix0,ix1) \ 175 do { \ 176 ieee_extended_shape_type iw_u; \ 177 iw_u.parts.exp = (se); \ 178 iw_u.parts.msw = (ix0); \ 179 iw_u.parts.lsw = (ix1); \ 180 (d) = iw_u.value; \ 181 } while (0) 182 183 /* Get the more significant 32 bits of a long double mantissa. */ 184 185 #define GET_LDOUBLE_MSW(v,d) \ 186 do { \ 187 ieee_extended_shape_type sh_u; \ 188 sh_u.value = (d); \ 189 (v) = sh_u.parts.msw; \ 190 } while (0) 191 192 /* Set the more significant 32 bits of a long double mantissa from an int. */ 193 194 #define SET_LDOUBLE_MSW(d,v) \ 195 do { \ 196 ieee_extended_shape_type sh_u; \ 197 sh_u.value = (d); \ 198 sh_u.parts.msw = (v); \ 199 (d) = sh_u.value; \ 200 } while (0) 201 202 /* Get int from the exponent of a long double. */ 203 204 #define GET_LDOUBLE_EXP(se,d) \ 205 do { \ 206 ieee_extended_shape_type ge_u; \ 207 ge_u.value = (d); \ 208 (se) = ge_u.parts.exp; \ 209 } while (0) 210 211 /* Set exponent of a long double from an int. */ 212 213 #define SET_LDOUBLE_EXP(d,se) \ 214 do { \ 215 ieee_extended_shape_type se_u; \ 216 se_u.value = (d); \ 217 se_u.parts.exp = (se); \ 218 (d) = se_u.value; \ 219 } while (0) 220 221 /* A union which permits us to convert between a double and two 32 bit 222 ints. */ 223 224 /* 225 * The arm port is little endian except for the FP word order which is 226 * big endian. 227 */ 228 229 #if (BYTE_ORDER == BIG_ENDIAN) || (defined(__arm__) && !defined(__VFP_FP__)) 230 231 typedef union 232 { 233 double value; 234 struct 235 { 236 u_int32_t msw; 237 u_int32_t lsw; 238 } parts; 239 } ieee_double_shape_type; 240 241 #endif 242 243 #if (BYTE_ORDER == LITTLE_ENDIAN) && !(defined(__arm__) && !defined(__VFP_FP__)) 244 245 typedef union 246 { 247 double value; 248 struct 249 { 250 u_int32_t lsw; 251 u_int32_t msw; 252 } parts; 253 } ieee_double_shape_type; 254 255 #endif 256 257 /* Get two 32 bit ints from a double. */ 258 259 #define EXTRACT_WORDS(ix0,ix1,d) \ 260 do { \ 261 ieee_double_shape_type ew_u; \ 262 ew_u.value = (d); \ 263 (ix0) = ew_u.parts.msw; \ 264 (ix1) = ew_u.parts.lsw; \ 265 } while (0) 266 267 /* Get the more significant 32 bit int from a double. */ 268 269 #define GET_HIGH_WORD(i,d) \ 270 do { \ 271 ieee_double_shape_type gh_u; \ 272 gh_u.value = (d); \ 273 (i) = gh_u.parts.msw; \ 274 } while (0) 275 276 /* Get the less significant 32 bit int from a double. */ 277 278 #define GET_LOW_WORD(i,d) \ 279 do { \ 280 ieee_double_shape_type gl_u; \ 281 gl_u.value = (d); \ 282 (i) = gl_u.parts.lsw; \ 283 } while (0) 284 285 /* Set a double from two 32 bit ints. */ 286 287 #define INSERT_WORDS(d,ix0,ix1) \ 288 do { \ 289 ieee_double_shape_type iw_u; \ 290 iw_u.parts.msw = (ix0); \ 291 iw_u.parts.lsw = (ix1); \ 292 (d) = iw_u.value; \ 293 } while (0) 294 295 /* Set the more significant 32 bits of a double from an int. */ 296 297 #define SET_HIGH_WORD(d,v) \ 298 do { \ 299 ieee_double_shape_type sh_u; \ 300 sh_u.value = (d); \ 301 sh_u.parts.msw = (v); \ 302 (d) = sh_u.value; \ 303 } while (0) 304 305 /* Set the less significant 32 bits of a double from an int. */ 306 307 #define SET_LOW_WORD(d,v) \ 308 do { \ 309 ieee_double_shape_type sl_u; \ 310 sl_u.value = (d); \ 311 sl_u.parts.lsw = (v); \ 312 (d) = sl_u.value; \ 313 } while (0) 314 315 /* A union which permits us to convert between a float and a 32 bit 316 int. */ 317 318 typedef union 319 { 320 float value; 321 u_int32_t word; 322 } ieee_float_shape_type; 323 324 /* Get a 32 bit int from a float. */ 325 326 #define GET_FLOAT_WORD(i,d) \ 327 do { \ 328 ieee_float_shape_type gf_u; \ 329 gf_u.value = (d); \ 330 (i) = gf_u.word; \ 331 } while (0) 332 333 /* Set a float from a 32 bit int. */ 334 335 #define SET_FLOAT_WORD(d,i) \ 336 do { \ 337 ieee_float_shape_type sf_u; \ 338 sf_u.word = (i); \ 339 (d) = sf_u.value; \ 340 } while (0) 341 342 #ifdef FLT_EVAL_METHOD 343 /* 344 * Attempt to get strict C99 semantics for assignment with non-C99 compilers. 345 */ 346 #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0 347 #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval)) 348 #else /* FLT_EVAL_METHOD == 0 || __GNUC__ == 0 */ 349 #define STRICT_ASSIGN(type, lval, rval) do { \ 350 volatile type __lval; \ 351 \ 352 if (sizeof(type) >= sizeof(long double)) \ 353 (lval) = (rval); \ 354 else { \ 355 __lval = (rval); \ 356 (lval) = __lval; \ 357 } \ 358 } while (0) 359 #endif /* FLT_EVAL_METHOD == 0 || __GNUC__ == 0 */ 360 #endif /* FLT_EVAL_METHOD */ 361 362 __BEGIN_HIDDEN_DECLS 363 /* fdlibm kernel function */ 364 extern int __ieee754_rem_pio2(double,double*); 365 extern double __kernel_sin(double,double,int); 366 extern double __kernel_cos(double,double); 367 extern double __kernel_tan(double,double,int); 368 extern int __kernel_rem_pio2(double*,double*,int,int,int); 369 370 /* float versions of fdlibm kernel functions */ 371 extern int __ieee754_rem_pio2f(float,float*); 372 extern float __kernel_sinf(float,float,int); 373 extern float __kernel_cosf(float,float); 374 extern float __kernel_tanf(float,float,int); 375 extern int __kernel_rem_pio2f(float*,float*,int,int,int,const int*); 376 377 /* long double precision kernel functions */ 378 long double __kernel_sinl(long double, long double, int); 379 long double __kernel_cosl(long double, long double); 380 long double __kernel_tanl(long double, long double, int); 381 382 /* 383 * Common routine to process the arguments to nan(), nanf(), and nanl(). 384 */ 385 void _scan_nan(uint32_t *__words, int __num_words, const char *__s); 386 __END_HIDDEN_DECLS 387 388 /* 389 * TRUNC() is a macro that sets the trailing 27 bits in the mantissa 390 * of an IEEE double variable to zero. It must be expression-like 391 * for syntactic reasons, and we implement this expression using 392 * an inline function instead of a pure macro to avoid depending 393 * on the gcc feature of statement-expressions. 394 */ 395 #define TRUNC(d) (_b_trunc(&(d))) 396 397 static __inline void 398 _b_trunc(volatile double *_dp) 399 { 400 uint32_t _lw; 401 402 GET_LOW_WORD(_lw, *_dp); 403 SET_LOW_WORD(*_dp, _lw & 0xf8000000); 404 } 405 406 struct Double { 407 double a; 408 double b; 409 }; 410 411 /* 412 * Functions internal to the math package, yet not static. 413 */ 414 __BEGIN_HIDDEN_DECLS 415 double __exp__D(double, double); 416 struct Double __log__D(double); 417 long double __p1evll(long double, void *, int); 418 long double __polevll(long double, void *, int); 419 __END_HIDDEN_DECLS 420 421 #endif /* _MATH_PRIVATE_H_ */ 422