13a8617a8SJordan K. Hubbard /* 23a8617a8SJordan K. Hubbard * ==================================================== 33a8617a8SJordan K. Hubbard * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 43a8617a8SJordan K. Hubbard * 53a8617a8SJordan K. Hubbard * Developed at SunPro, a Sun Microsystems, Inc. business. 63a8617a8SJordan K. Hubbard * Permission to use, copy, modify, and distribute this 73a8617a8SJordan K. Hubbard * software is freely granted, provided that this notice 83a8617a8SJordan K. Hubbard * is preserved. 93a8617a8SJordan K. Hubbard * ==================================================== 103a8617a8SJordan K. Hubbard */ 113a8617a8SJordan K. Hubbard 123a8617a8SJordan K. Hubbard /* 133a8617a8SJordan K. Hubbard * from: @(#)fdlibm.h 5.1 93/09/24 147f3dea24SPeter Wemm * $FreeBSD$ 153a8617a8SJordan K. Hubbard */ 163a8617a8SJordan K. Hubbard 173a8617a8SJordan K. Hubbard #ifndef _MATH_PRIVATE_H_ 183a8617a8SJordan K. Hubbard #define _MATH_PRIVATE_H_ 193a8617a8SJordan K. Hubbard 203a8617a8SJordan K. Hubbard #include <sys/types.h> 21bcfa1759SBrian Somers #include <machine/endian.h> 223a8617a8SJordan K. Hubbard 23ef1ee63eSAlexey Zelkin /* 24ef1ee63eSAlexey Zelkin * The original fdlibm code used statements like: 25ef1ee63eSAlexey Zelkin * n0 = ((*(int*)&one)>>29)^1; * index of high word * 26ef1ee63eSAlexey Zelkin * ix0 = *(n0+(int*)&x); * high word of x * 27ef1ee63eSAlexey Zelkin * ix1 = *((1-n0)+(int*)&x); * low word of x * 28ef1ee63eSAlexey Zelkin * to dig two 32 bit words out of the 64 bit IEEE floating point 29ef1ee63eSAlexey Zelkin * value. That is non-ANSI, and, moreover, the gcc instruction 30ef1ee63eSAlexey Zelkin * scheduler gets it wrong. We instead use the following macros. 31ef1ee63eSAlexey Zelkin * Unlike the original code, we determine the endianness at compile 32ef1ee63eSAlexey Zelkin * time, not at run time; I don't see much benefit to selecting 33ef1ee63eSAlexey Zelkin * endianness at run time. 34ef1ee63eSAlexey Zelkin */ 353a8617a8SJordan K. Hubbard 36ef1ee63eSAlexey Zelkin /* 37ef1ee63eSAlexey Zelkin * A union which permits us to convert between a double and two 32 bit 38ef1ee63eSAlexey Zelkin * ints. 39ef1ee63eSAlexey Zelkin */ 403a8617a8SJordan K. Hubbard 4174aed985SMarcel Moolenaar #ifdef __arm__ 4274aed985SMarcel Moolenaar #if defined(__VFP_FP__) 4374aed985SMarcel Moolenaar #define IEEE_WORD_ORDER BYTE_ORDER 4474aed985SMarcel Moolenaar #else 4574aed985SMarcel Moolenaar #define IEEE_WORD_ORDER BIG_ENDIAN 4674aed985SMarcel Moolenaar #endif 4774aed985SMarcel Moolenaar #else /* __arm__ */ 4874aed985SMarcel Moolenaar #define IEEE_WORD_ORDER BYTE_ORDER 4974aed985SMarcel Moolenaar #endif 5074aed985SMarcel Moolenaar 5174aed985SMarcel Moolenaar #if IEEE_WORD_ORDER == BIG_ENDIAN 523a8617a8SJordan K. Hubbard 533a8617a8SJordan K. Hubbard typedef union 543a8617a8SJordan K. Hubbard { 553a8617a8SJordan K. Hubbard double value; 563a8617a8SJordan K. Hubbard struct 573a8617a8SJordan K. Hubbard { 583a8617a8SJordan K. Hubbard u_int32_t msw; 593a8617a8SJordan K. Hubbard u_int32_t lsw; 603a8617a8SJordan K. Hubbard } parts; 613a8617a8SJordan K. Hubbard } ieee_double_shape_type; 623a8617a8SJordan K. Hubbard 633a8617a8SJordan K. Hubbard #endif 643a8617a8SJordan K. Hubbard 6574aed985SMarcel Moolenaar #if IEEE_WORD_ORDER == LITTLE_ENDIAN 663a8617a8SJordan K. Hubbard 673a8617a8SJordan K. Hubbard typedef union 683a8617a8SJordan K. Hubbard { 693a8617a8SJordan K. Hubbard double value; 703a8617a8SJordan K. Hubbard struct 713a8617a8SJordan K. Hubbard { 723a8617a8SJordan K. Hubbard u_int32_t lsw; 733a8617a8SJordan K. Hubbard u_int32_t msw; 743a8617a8SJordan K. Hubbard } parts; 753a8617a8SJordan K. Hubbard } ieee_double_shape_type; 763a8617a8SJordan K. Hubbard 773a8617a8SJordan K. Hubbard #endif 783a8617a8SJordan K. Hubbard 793a8617a8SJordan K. Hubbard /* Get two 32 bit ints from a double. */ 803a8617a8SJordan K. Hubbard 813a8617a8SJordan K. Hubbard #define EXTRACT_WORDS(ix0,ix1,d) \ 823a8617a8SJordan K. Hubbard do { \ 833a8617a8SJordan K. Hubbard ieee_double_shape_type ew_u; \ 843a8617a8SJordan K. Hubbard ew_u.value = (d); \ 853a8617a8SJordan K. Hubbard (ix0) = ew_u.parts.msw; \ 863a8617a8SJordan K. Hubbard (ix1) = ew_u.parts.lsw; \ 873a8617a8SJordan K. Hubbard } while (0) 883a8617a8SJordan K. Hubbard 893a8617a8SJordan K. Hubbard /* Get the more significant 32 bit int from a double. */ 903a8617a8SJordan K. Hubbard 913a8617a8SJordan K. Hubbard #define GET_HIGH_WORD(i,d) \ 923a8617a8SJordan K. Hubbard do { \ 933a8617a8SJordan K. Hubbard ieee_double_shape_type gh_u; \ 943a8617a8SJordan K. Hubbard gh_u.value = (d); \ 953a8617a8SJordan K. Hubbard (i) = gh_u.parts.msw; \ 963a8617a8SJordan K. Hubbard } while (0) 973a8617a8SJordan K. Hubbard 983a8617a8SJordan K. Hubbard /* Get the less significant 32 bit int from a double. */ 993a8617a8SJordan K. Hubbard 1003a8617a8SJordan K. Hubbard #define GET_LOW_WORD(i,d) \ 1013a8617a8SJordan K. Hubbard do { \ 1023a8617a8SJordan K. Hubbard ieee_double_shape_type gl_u; \ 1033a8617a8SJordan K. Hubbard gl_u.value = (d); \ 1043a8617a8SJordan K. Hubbard (i) = gl_u.parts.lsw; \ 1053a8617a8SJordan K. Hubbard } while (0) 1063a8617a8SJordan K. Hubbard 1073a8617a8SJordan K. Hubbard /* Set a double from two 32 bit ints. */ 1083a8617a8SJordan K. Hubbard 1093a8617a8SJordan K. Hubbard #define INSERT_WORDS(d,ix0,ix1) \ 1103a8617a8SJordan K. Hubbard do { \ 1113a8617a8SJordan K. Hubbard ieee_double_shape_type iw_u; \ 1123a8617a8SJordan K. Hubbard iw_u.parts.msw = (ix0); \ 1133a8617a8SJordan K. Hubbard iw_u.parts.lsw = (ix1); \ 1143a8617a8SJordan K. Hubbard (d) = iw_u.value; \ 1153a8617a8SJordan K. Hubbard } while (0) 1163a8617a8SJordan K. Hubbard 1173a8617a8SJordan K. Hubbard /* Set the more significant 32 bits of a double from an int. */ 1183a8617a8SJordan K. Hubbard 1193a8617a8SJordan K. Hubbard #define SET_HIGH_WORD(d,v) \ 1203a8617a8SJordan K. Hubbard do { \ 1213a8617a8SJordan K. Hubbard ieee_double_shape_type sh_u; \ 1223a8617a8SJordan K. Hubbard sh_u.value = (d); \ 1233a8617a8SJordan K. Hubbard sh_u.parts.msw = (v); \ 1243a8617a8SJordan K. Hubbard (d) = sh_u.value; \ 1253a8617a8SJordan K. Hubbard } while (0) 1263a8617a8SJordan K. Hubbard 1273a8617a8SJordan K. Hubbard /* Set the less significant 32 bits of a double from an int. */ 1283a8617a8SJordan K. Hubbard 1293a8617a8SJordan K. Hubbard #define SET_LOW_WORD(d,v) \ 1303a8617a8SJordan K. Hubbard do { \ 1313a8617a8SJordan K. Hubbard ieee_double_shape_type sl_u; \ 1323a8617a8SJordan K. Hubbard sl_u.value = (d); \ 1333a8617a8SJordan K. Hubbard sl_u.parts.lsw = (v); \ 1343a8617a8SJordan K. Hubbard (d) = sl_u.value; \ 1353a8617a8SJordan K. Hubbard } while (0) 1363a8617a8SJordan K. Hubbard 137ef1ee63eSAlexey Zelkin /* 138ef1ee63eSAlexey Zelkin * A union which permits us to convert between a float and a 32 bit 139ef1ee63eSAlexey Zelkin * int. 140ef1ee63eSAlexey Zelkin */ 1413a8617a8SJordan K. Hubbard 1423a8617a8SJordan K. Hubbard typedef union 1433a8617a8SJordan K. Hubbard { 1443a8617a8SJordan K. Hubbard float value; 1453a8617a8SJordan K. Hubbard /* FIXME: Assumes 32 bit int. */ 1463a8617a8SJordan K. Hubbard unsigned int word; 1473a8617a8SJordan K. Hubbard } ieee_float_shape_type; 1483a8617a8SJordan K. Hubbard 1493a8617a8SJordan K. Hubbard /* Get a 32 bit int from a float. */ 1503a8617a8SJordan K. Hubbard 1513a8617a8SJordan K. Hubbard #define GET_FLOAT_WORD(i,d) \ 1523a8617a8SJordan K. Hubbard do { \ 1533a8617a8SJordan K. Hubbard ieee_float_shape_type gf_u; \ 1543a8617a8SJordan K. Hubbard gf_u.value = (d); \ 1553a8617a8SJordan K. Hubbard (i) = gf_u.word; \ 1563a8617a8SJordan K. Hubbard } while (0) 1573a8617a8SJordan K. Hubbard 1583a8617a8SJordan K. Hubbard /* Set a float from a 32 bit int. */ 1593a8617a8SJordan K. Hubbard 1603a8617a8SJordan K. Hubbard #define SET_FLOAT_WORD(d,i) \ 1613a8617a8SJordan K. Hubbard do { \ 1623a8617a8SJordan K. Hubbard ieee_float_shape_type sf_u; \ 1633a8617a8SJordan K. Hubbard sf_u.word = (i); \ 1643a8617a8SJordan K. Hubbard (d) = sf_u.value; \ 1653a8617a8SJordan K. Hubbard } while (0) 1663a8617a8SJordan K. Hubbard 1671880ccbdSBruce Evans #ifdef FLT_EVAL_METHOD 1681880ccbdSBruce Evans /* 1691880ccbdSBruce Evans * Attempt to get strict C99 semantics for assignment with non-C99 compilers. 1701880ccbdSBruce Evans */ 1711880ccbdSBruce Evans #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0 1721880ccbdSBruce Evans #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval)) 1731880ccbdSBruce Evans #else 1741880ccbdSBruce Evans #define STRICT_ASSIGN(type, lval, rval) do { \ 1751880ccbdSBruce Evans volatile type __lval; \ 1761880ccbdSBruce Evans \ 1775b62c380SBruce Evans if (sizeof(type) >= sizeof(double)) \ 1785b62c380SBruce Evans (lval) = (rval); \ 1795b62c380SBruce Evans else { \ 1801880ccbdSBruce Evans __lval = (rval); \ 1811880ccbdSBruce Evans (lval) = __lval; \ 1825b62c380SBruce Evans } \ 1831880ccbdSBruce Evans } while (0) 1841880ccbdSBruce Evans #endif 1851880ccbdSBruce Evans #endif 1861880ccbdSBruce Evans 1877cd4a832SDavid Schultz /* 1887cd4a832SDavid Schultz * Common routine to process the arguments to nan(), nanf(), and nanl(). 1897cd4a832SDavid Schultz */ 1907cd4a832SDavid Schultz void _scan_nan(uint32_t *__words, int __num_words, const char *__s); 1917cd4a832SDavid Schultz 19219b114daSBruce Evans #ifdef _COMPLEX_H 19319b114daSBruce Evans /* 19419b114daSBruce Evans * Inline functions that can be used to construct complex values. 19519b114daSBruce Evans * 19619b114daSBruce Evans * The C99 standard intends x+I*y to be used for this, but x+I*y is 19719b114daSBruce Evans * currently unusable in general since gcc introduces many overflow, 19819b114daSBruce Evans * underflow, sign and efficiency bugs by rewriting I*y as 19919b114daSBruce Evans * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product. 20019b114daSBruce Evans * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted 20119b114daSBruce Evans * to -0.0+I*0.0. 20219b114daSBruce Evans */ 20319b114daSBruce Evans static __inline float complex 20419b114daSBruce Evans cpackf(float x, float y) 20519b114daSBruce Evans { 20619b114daSBruce Evans float complex z; 20719b114daSBruce Evans 20819b114daSBruce Evans __real__ z = x; 20919b114daSBruce Evans __imag__ z = y; 21019b114daSBruce Evans return (z); 21119b114daSBruce Evans } 21219b114daSBruce Evans 21319b114daSBruce Evans static __inline double complex 21419b114daSBruce Evans cpack(double x, double y) 21519b114daSBruce Evans { 21619b114daSBruce Evans double complex z; 21719b114daSBruce Evans 21819b114daSBruce Evans __real__ z = x; 21919b114daSBruce Evans __imag__ z = y; 22019b114daSBruce Evans return (z); 22119b114daSBruce Evans } 22219b114daSBruce Evans 22319b114daSBruce Evans static __inline long double complex 22419b114daSBruce Evans cpackl(long double x, long double y) 22519b114daSBruce Evans { 22619b114daSBruce Evans long double complex z; 22719b114daSBruce Evans 22819b114daSBruce Evans __real__ z = x; 22919b114daSBruce Evans __imag__ z = y; 23019b114daSBruce Evans return (z); 23119b114daSBruce Evans } 23219b114daSBruce Evans #endif /* _COMPLEX_H */ 23319b114daSBruce Evans 2340ddfa46bSBruce Evans #ifdef __GNUCLIKE_ASM 2350ddfa46bSBruce Evans 2360ddfa46bSBruce Evans /* Asm versions of some functions. */ 2370ddfa46bSBruce Evans 2380ddfa46bSBruce Evans #ifdef __amd64__ 2390ddfa46bSBruce Evans static __inline int 2400ddfa46bSBruce Evans irint(double x) 2410ddfa46bSBruce Evans { 2420ddfa46bSBruce Evans int n; 2430ddfa46bSBruce Evans 2440ddfa46bSBruce Evans asm("cvtsd2si %1,%0" : "=r" (n) : "Y" (x)); 2450ddfa46bSBruce Evans return (n); 2460ddfa46bSBruce Evans } 2470ddfa46bSBruce Evans #define HAVE_EFFICIENT_IRINT 2480ddfa46bSBruce Evans #endif 2490ddfa46bSBruce Evans 2500ddfa46bSBruce Evans #ifdef __i386__ 2510ddfa46bSBruce Evans static __inline int 2520ddfa46bSBruce Evans irint(double x) 2530ddfa46bSBruce Evans { 2540ddfa46bSBruce Evans int n; 2550ddfa46bSBruce Evans 2560ddfa46bSBruce Evans asm("fistl %0" : "=m" (n) : "t" (x)); 2570ddfa46bSBruce Evans return (n); 2580ddfa46bSBruce Evans } 2590ddfa46bSBruce Evans #define HAVE_EFFICIENT_IRINT 2600ddfa46bSBruce Evans #endif 2610ddfa46bSBruce Evans 2620ddfa46bSBruce Evans #endif /* __GNUCLIKE_ASM */ 2630ddfa46bSBruce Evans 264e1b61b5bSDavid Schultz /* 265e1b61b5bSDavid Schultz * ieee style elementary functions 266e1b61b5bSDavid Schultz * 267e1b61b5bSDavid Schultz * We rename functions here to improve other sources' diffability 268e1b61b5bSDavid Schultz * against fdlibm. 269e1b61b5bSDavid Schultz */ 270e1b61b5bSDavid Schultz #define __ieee754_sqrt sqrt 271e1b61b5bSDavid Schultz #define __ieee754_acos acos 272e1b61b5bSDavid Schultz #define __ieee754_acosh acosh 273e1b61b5bSDavid Schultz #define __ieee754_log log 274e1b61b5bSDavid Schultz #define __ieee754_atanh atanh 275e1b61b5bSDavid Schultz #define __ieee754_asin asin 276e1b61b5bSDavid Schultz #define __ieee754_atan2 atan2 277e1b61b5bSDavid Schultz #define __ieee754_exp exp 278e1b61b5bSDavid Schultz #define __ieee754_cosh cosh 279e1b61b5bSDavid Schultz #define __ieee754_fmod fmod 280e1b61b5bSDavid Schultz #define __ieee754_pow pow 281e1b61b5bSDavid Schultz #define __ieee754_lgamma lgamma 282e1b61b5bSDavid Schultz #define __ieee754_gamma gamma 283e1b61b5bSDavid Schultz #define __ieee754_lgamma_r lgamma_r 284e1b61b5bSDavid Schultz #define __ieee754_gamma_r gamma_r 285e1b61b5bSDavid Schultz #define __ieee754_log10 log10 286e1b61b5bSDavid Schultz #define __ieee754_sinh sinh 287e1b61b5bSDavid Schultz #define __ieee754_hypot hypot 288e1b61b5bSDavid Schultz #define __ieee754_j0 j0 289e1b61b5bSDavid Schultz #define __ieee754_j1 j1 290e1b61b5bSDavid Schultz #define __ieee754_y0 y0 291e1b61b5bSDavid Schultz #define __ieee754_y1 y1 292e1b61b5bSDavid Schultz #define __ieee754_jn jn 293e1b61b5bSDavid Schultz #define __ieee754_yn yn 294e1b61b5bSDavid Schultz #define __ieee754_remainder remainder 295e1b61b5bSDavid Schultz #define __ieee754_scalb scalb 296e1b61b5bSDavid Schultz #define __ieee754_sqrtf sqrtf 297e1b61b5bSDavid Schultz #define __ieee754_acosf acosf 298e1b61b5bSDavid Schultz #define __ieee754_acoshf acoshf 299e1b61b5bSDavid Schultz #define __ieee754_logf logf 300e1b61b5bSDavid Schultz #define __ieee754_atanhf atanhf 301e1b61b5bSDavid Schultz #define __ieee754_asinf asinf 302e1b61b5bSDavid Schultz #define __ieee754_atan2f atan2f 303e1b61b5bSDavid Schultz #define __ieee754_expf expf 304e1b61b5bSDavid Schultz #define __ieee754_coshf coshf 305e1b61b5bSDavid Schultz #define __ieee754_fmodf fmodf 306e1b61b5bSDavid Schultz #define __ieee754_powf powf 307e1b61b5bSDavid Schultz #define __ieee754_lgammaf lgammaf 308e1b61b5bSDavid Schultz #define __ieee754_gammaf gammaf 309e1b61b5bSDavid Schultz #define __ieee754_lgammaf_r lgammaf_r 310e1b61b5bSDavid Schultz #define __ieee754_gammaf_r gammaf_r 311e1b61b5bSDavid Schultz #define __ieee754_log10f log10f 312e1b61b5bSDavid Schultz #define __ieee754_sinhf sinhf 313e1b61b5bSDavid Schultz #define __ieee754_hypotf hypotf 314e1b61b5bSDavid Schultz #define __ieee754_j0f j0f 315e1b61b5bSDavid Schultz #define __ieee754_j1f j1f 316e1b61b5bSDavid Schultz #define __ieee754_y0f y0f 317e1b61b5bSDavid Schultz #define __ieee754_y1f y1f 318e1b61b5bSDavid Schultz #define __ieee754_jnf jnf 319e1b61b5bSDavid Schultz #define __ieee754_ynf ynf 320e1b61b5bSDavid Schultz #define __ieee754_remainderf remainderf 321e1b61b5bSDavid Schultz #define __ieee754_scalbf scalbf 3223a8617a8SJordan K. Hubbard 3233a8617a8SJordan K. Hubbard /* fdlibm kernel function */ 324079299f7SDavid Schultz int __kernel_rem_pio2(double*,double*,int,int,int); 325079299f7SDavid Schultz 326079299f7SDavid Schultz /* double precision kernel functions */ 327e02846ceSDavid Schultz int __ieee754_rem_pio2(double,double*); 32869160b1eSDavid E. O'Brien double __kernel_sin(double,double,int); 32969160b1eSDavid E. O'Brien double __kernel_cos(double,double); 33069160b1eSDavid E. O'Brien double __kernel_tan(double,double,int); 3313a8617a8SJordan K. Hubbard 332079299f7SDavid Schultz /* float precision kernel functions */ 33370d818a2SBruce Evans int __ieee754_rem_pio2f(float,double*); 33459aad933SBruce Evans float __kernel_sindf(double); 33559aad933SBruce Evans float __kernel_cosdf(double); 33694a5f9beSBruce Evans float __kernel_tandf(double,int); 337079299f7SDavid Schultz 338079299f7SDavid Schultz /* long double precision kernel functions */ 339079299f7SDavid Schultz long double __kernel_sinl(long double, long double, int); 340079299f7SDavid Schultz long double __kernel_cosl(long double, long double); 341079299f7SDavid Schultz long double __kernel_tanl(long double, long double, int); 3423a8617a8SJordan K. Hubbard 343ef1ee63eSAlexey Zelkin #endif /* !_MATH_PRIVATE_H_ */ 344