2 * ====================================================
3 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
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
9 * ====================================================
13 * from: @(#)fdlibm.h 5.1 93/09/24
14 * $NetBSD: math_private.h,v 1.16 2010/09/16 20:39:50 drochner Exp $
17 #ifndef _MATH_PRIVATE_H_
18 #define _MATH_PRIVATE_H_
20 #include <sys/types.h>
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. */
33 /* A union which permits us to convert between a double and two 32 bit
37 * The ARM ports are little endian except for the FPA word order which is
41 #if BYTE_ORDER == BIG_ENDIAN
55 } ieee_double_shape_type;
59 #if BYTE_ORDER == LITTLE_ENDIAN
73 } ieee_double_shape_type;
77 /* Get two 32 bit ints from a double. */
79 #define EXTRACT_WORDS(ix0,ix1,d) \
81 ieee_double_shape_type ew_u; \
83 (ix0) = ew_u.parts.msw; \
84 (ix1) = ew_u.parts.lsw; \
85 } while (/*CONSTCOND*/0)
88 * Get a 64-bit int from a double.
89 * Origin: FreeBSD msun/src/math_private.h
91 #define EXTRACT_WORD64(ix,d) \
93 ieee_double_shape_type ew_u; \
95 (ix) = ew_u.xparts.w; \
98 /* Get the more significant 32 bit int from a double. */
100 #define GET_HIGH_WORD(i,d) \
102 ieee_double_shape_type gh_u; \
104 (i) = gh_u.parts.msw; \
105 } while (/*CONSTCOND*/0)
107 /* Get the less significant 32 bit int from a double. */
109 #define GET_LOW_WORD(i,d) \
111 ieee_double_shape_type gl_u; \
113 (i) = gl_u.parts.lsw; \
114 } while (/*CONSTCOND*/0)
116 /* Set a double from two 32 bit ints. */
118 #define INSERT_WORDS(d,ix0,ix1) \
120 ieee_double_shape_type iw_u; \
121 iw_u.parts.msw = (ix0); \
122 iw_u.parts.lsw = (ix1); \
124 } while (/*CONSTCOND*/0)
127 * Set a double from a 64-bit int.
128 * Origin: FreeBSD msun/src/math_private.h
130 #define INSERT_WORD64(d,ix) \
132 ieee_double_shape_type iw_u; \
133 iw_u.xparts.w = (ix); \
137 /* Set the more significant 32 bits of a double from an int. */
139 #define SET_HIGH_WORD(d,v) \
141 ieee_double_shape_type sh_u; \
143 sh_u.parts.msw = (v); \
145 } while (/*CONSTCOND*/0)
147 /* Set the less significant 32 bits of a double from an int. */
149 #define SET_LOW_WORD(d,v) \
151 ieee_double_shape_type sl_u; \
153 sl_u.parts.lsw = (v); \
155 } while (/*CONSTCOND*/0)
157 /* A union which permits us to convert between a float and a 32 bit
164 } ieee_float_shape_type;
166 /* Get a 32 bit int from a float. */
168 #define GET_FLOAT_WORD(i,d) \
170 ieee_float_shape_type gf_u; \
173 } while (/*CONSTCOND*/0)
175 /* Set a float from a 32 bit int. */
177 #define SET_FLOAT_WORD(d,i) \
179 ieee_float_shape_type sf_u; \
182 } while (/*CONSTCOND*/0)
185 * Get expsign as a 16 bit int from a long double.
186 * Origin: FreeBSD msun/src/math_private.h
189 #define GET_LDBL_EXPSIGN(i,d) \
191 union IEEEl2bits ge_u; \
193 (i) = ge_u.xbits.expsign; \
194 } while (/*CONSTCOND*/0)
197 * Set expsign of a long double from a 16 bit int.
200 #define SET_LDBL_EXPSIGN(d,v) \
202 union IEEEl2bits se_u; \
204 se_u.xbits.expsign = (v); \
206 } while (/*CONSTCOND*/0)
209 * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
211 #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
212 #define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
214 #define STRICT_ASSIGN(type, lval, rval) do { \
215 volatile type __lval; \
217 if (sizeof(type) >= sizeof(double)) \
223 } while (/*CONSTCOND*/0)
229 * Quoting from ISO/IEC 9899:TC2:
232 * Each complex type has the same representation and alignment requirements as
233 * an array type containing exactly two elements of the corresponding real type;
234 * the first element is equal to the real part, and the second element to the
235 * imaginary part, of the complex number.
248 long double complex z;
249 long double parts[2];
250 } long_double_complex;
252 #define REAL_PART(z) ((z).parts[0])
253 #define IMAG_PART(z) ((z).parts[1])
256 * Inline functions that can be used to construct complex values.
258 * The C99 standard intends x+I*y to be used for this, but x+I*y is
259 * currently unusable in general since gcc introduces many overflow,
260 * underflow, sign and efficiency bugs by rewriting I*y as
261 * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product.
262 * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted
265 static __inline float complex
266 cpackf(float x, float y)
275 static __inline double complex
276 cpack(double x, double y)
285 static __inline long double complex
286 cpackl(long double x, long double y)
288 long_double_complex ldc;
295 #endif /* _COMPLEX_H */
298 #pragma GCC visibility push(hidden)
300 /* fdlibm kernel function */
301 int __kernel_rem_pio2(double*,double*,int,int,int);
303 /* double precision kernel functions */
304 int __libm_rem_pio2(double, double*);
305 double __kernel_sin(double, double, int);
306 double __kernel_cos(double, double);
307 double __kernel_tan(double, double, int);
309 /* float precision kernel functions */
310 int __libm_rem_pio2f(float,double*);
311 float __kernel_sindf(double);
312 float __kernel_cosdf(double);
313 float __kernel_tandf(double, int);
315 /* long double precision kernel functions */
316 long double __kernel_sinl(long double, long double, int);
317 long double __kernel_cosl(long double, long double);
318 long double __kernel_tanl(long double, long double, int);
320 #pragma GCC visibility pop
323 #endif /* _MATH_PRIVATE_H_ */